pkgsrc-Changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

CVS commit: pkgsrc/www



Module Name:    pkgsrc
Committed By:   nia
Date:           Fri Apr 25 21:25:03 UTC 2025

Modified Files:
        pkgsrc/www: Makefile
Added Files:
        pkgsrc/www/basilisk: DESCR Makefile PLIST PLIST.Linux PLIST.NetBSD
            distinfo hacks.mk options.mk
        pkgsrc/www/basilisk/patches: patch-platform_build_moz.build
            patch-platform_gfx_angle_src_libANGLE_renderer_gl_glx_FunctionsGLX.cpp
            patch-platform_intl_icu_source_configure
            patch-platform_ipc_chromium_src_base_atomicops.h
            patch-platform_ipc_chromium_src_base_atomicops__internals__arm__gcc.h
            patch-platform_media_libaom_config_linux_arm_config_aom__config.h
            patch-platform_media_libcubeb_src_cubeb__sun.c
            patch-platform_media_libtheora_moz.build
            patch-platform_media_libvpx_config_linux_arm_vpx__config.h
            patch-platform_media_webrtc_trunk_webrtc_modules_audio__device_audio__device.gypi
            patch-platform_netwerk_srtp_src_crypto_hash_hmac.c
            patch-platform_netwerk_srtp_src_crypto_kernel_crypto__kernel.c
            patch-platform_nsprpub_pr_include_md__netbsd.cfg
            patch-platform_nsprpub_pr_include_md__netbsd.h
            patch-platform_nsprpub_pr_include_private_pprthred.h
            patch-platform_nsprpub_pr_src_pthreads_ptsynch.c
            patch-platform_nsprpub_pr_src_pthreads_ptthread.c
            patch-platform_security_generate__mapfile.py
            patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops.h
            patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops__internals__arm__gcc.h
            patch-platform_toolkit_xre_nsX11ErrorHandler.cpp
            patch-platform_xpcom_reflect_xptcall_md_unix_xptcinvoke__arm__netbsd.cpp
            patch-platform_xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp

Log Message:
basilisk: Initial import of the Basilisk web browser

Basilisk is an UXP-based web browser inspired by pre-Servo
Firefox but using the Goanna engine from Pale Moon. It's essentially
Pale Moon with a user interface more like www/firefox52.


To generate a diff of this commit:
cvs rdiff -u -r1.1857 -r1.1858 pkgsrc/www/Makefile
cvs rdiff -u -r0 -r1.1 pkgsrc/www/basilisk/DESCR pkgsrc/www/basilisk/Makefile \
    pkgsrc/www/basilisk/PLIST pkgsrc/www/basilisk/PLIST.Linux \
    pkgsrc/www/basilisk/PLIST.NetBSD pkgsrc/www/basilisk/distinfo \
    pkgsrc/www/basilisk/hacks.mk pkgsrc/www/basilisk/options.mk
cvs rdiff -u -r0 -r1.1 \
    pkgsrc/www/basilisk/patches/patch-platform_build_moz.build \
    pkgsrc/www/basilisk/patches/patch-platform_gfx_angle_src_libANGLE_renderer_gl_glx_FunctionsGLX.cpp \
    pkgsrc/www/basilisk/patches/patch-platform_intl_icu_source_configure \
    pkgsrc/www/basilisk/patches/patch-platform_ipc_chromium_src_base_atomicops.h \
    pkgsrc/www/basilisk/patches/patch-platform_ipc_chromium_src_base_atomicops__internals__arm__gcc.h \
    pkgsrc/www/basilisk/patches/patch-platform_media_libaom_config_linux_arm_config_aom__config.h \
    pkgsrc/www/basilisk/patches/patch-platform_media_libcubeb_src_cubeb__sun.c \
    pkgsrc/www/basilisk/patches/patch-platform_media_libtheora_moz.build \
    pkgsrc/www/basilisk/patches/patch-platform_media_libvpx_config_linux_arm_vpx__config.h \
    pkgsrc/www/basilisk/patches/patch-platform_media_webrtc_trunk_webrtc_modules_audio__device_audio__device.gypi \
    pkgsrc/www/basilisk/patches/patch-platform_netwerk_srtp_src_crypto_hash_hmac.c \
    pkgsrc/www/basilisk/patches/patch-platform_netwerk_srtp_src_crypto_kernel_crypto__kernel.c \
    pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_md__netbsd.cfg \
    pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_md__netbsd.h \
    pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_private_pprthred.h \
    pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_src_pthreads_ptsynch.c \
    pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_src_pthreads_ptthread.c \
    pkgsrc/www/basilisk/patches/patch-platform_security_generate__mapfile.py \
    pkgsrc/www/basilisk/patches/patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops.h \
    pkgsrc/www/basilisk/patches/patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops__internals__arm__gcc.h \
    pkgsrc/www/basilisk/patches/patch-platform_toolkit_xre_nsX11ErrorHandler.cpp \
    pkgsrc/www/basilisk/patches/patch-platform_xpcom_reflect_xptcall_md_unix_xptcinvoke__arm__netbsd.cpp \
    pkgsrc/www/basilisk/patches/patch-platform_xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: pkgsrc/www/Makefile
diff -u pkgsrc/www/Makefile:1.1857 pkgsrc/www/Makefile:1.1858
--- pkgsrc/www/Makefile:1.1857  Tue Apr 22 15:15:01 2025
+++ pkgsrc/www/Makefile Fri Apr 25 21:25:03 2025
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.1857 2025/04/22 15:15:01 adam Exp $
+# $NetBSD: Makefile,v 1.1858 2025/04/25 21:25:03 nia Exp $
 #
 
 COMMENT=       Packages related to the World Wide Web
@@ -73,6 +73,7 @@ SUBDIR+=      august
 SUBDIR+=       awstats
 SUBDIR+=       badwolf
 SUBDIR+=       bannerfilter
+SUBDIR+=       basilisk
 SUBDIR+=       bins
 SUBDIR+=       bkedit
 SUBDIR+=       bluefish

Added files:

Index: pkgsrc/www/basilisk/DESCR
diff -u /dev/null pkgsrc/www/basilisk/DESCR:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/DESCR   Fri Apr 25 21:25:03 2025
@@ -0,0 +1,7 @@
+Basilisk is a free and Open Source XUL-based web browser, featuring the
+well-known Firefox-style interface and operation. It is based on the Goanna
+layout and rendering engine (a fork of Gecko) and builds on the Unified
+XUL Platform (UXP), which in turn is a fork of the Mozilla code base
+without Servo or Rust.
+
+Basilisk supports a wide array of features required for the Modern Web.
Index: pkgsrc/www/basilisk/Makefile
diff -u /dev/null pkgsrc/www/basilisk/Makefile:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/Makefile        Fri Apr 25 21:25:03 2025
@@ -0,0 +1,174 @@
+# $NetBSD: Makefile,v 1.1 2025/04/25 21:25:03 nia Exp $
+# This package is mostly derived from www/palemoon since they use the
+# same backend.  However, several key things are different.
+
+PKGNAME=       basilisk-2025.04.23
+CATEGORIES=    www
+
+DIST_SUBDIR=   basilisk-${PKGVERSION_NOREV}
+DISTFILES+=    basilisk.tar.gz
+DISTFILES+=    uxp.tar.gz
+DISTFILES+=    psutil.tar.gz
+
+SITES.basilisk.tar.gz= \
+       -https://repo.palemoon.org/Basilisk-Dev/Basilisk/archive/v${PKGVERSION_NOREV}.tar.gz
+
+SITES.uxp.tar.gz= \
+       -https://repo.palemoon.org/MoonchildProductions/UXP/archive/d892468fd052cb8961b7e36d5b087e53eb625f8e.tar.gz
+
+SITES.psutil.tar.gz= \
+       -https://files.pythonhosted.org/packages/7b/58/2675697b6831e6ac4b7b7bc4e5dcdb24a2f39f8411186573eb0de16eb6d5/psutil-3.4.2.tar.gz
+
+MAINTAINER=    nia%NetBSD.org@localhost
+HOMEPAGE=      https://www.basilisk-browser.org/
+COMMENT=       UXP-based web browser inspired by pre-Servo Firefox
+LICENSE=       mpl-2.0
+
+USE_TOOLS+=    perl pkg-config autoconf213
+USE_TOOLS+=    zip unzip gmake
+
+HAS_CONFIGURE= yes
+USE_LANGUAGES= c c++
+
+# "ERROR: Only GCC 9.1 or newer is supported"
+# Use GCC 10 because 9 is untested.
+GCC_REQD+=     10
+
+WRKSRC=                ${WRKDIR}/basilisk
+
+LDFLAGS+=      ${COMPILER_RPATH_FLAG}${PREFIX}/lib/basilisk-52.9.0
+
+CONFIG_GUESS_OVERRIDE+=        platform/build/autoconf/config.guess
+CONFIG_GUESS_OVERRIDE+=        platform/intl/icu/source/config.guess
+CONFIG_GUESS_OVERRIDE+=        platform/ipc/chromium/src/third_party/libevent/config.guess
+CONFIG_GUESS_OVERRIDE+=        platform/js/src/ctypes/libffi/config.guess
+CONFIG_GUESS_OVERRIDE+=        platform/nsprpub/build/autoconf/config.guess
+
+CONFIG_SUB_OVERRIDE+=  platform/build/autoconf/config.sub
+CONFIG_SUB_OVERRIDE+=  platform/intl/icu/source/config.sub
+CONFIG_SUB_OVERRIDE+=  platform/ipc/chromium/src/third_party/libevent/config.sub
+CONFIG_SUB_OVERRIDE+=  platform/js/src/ctypes/libffi/config.sub
+CONFIG_SUB_OVERRIDE+=  platform/nsprpub/build/autoconf/config.sub
+
+CONFIGURE_DIRS=                ${WRKDIR}/build
+CONFIGURE_SCRIPT=      ${WRKSRC}/configure
+
+# see basilisk/mozconfigs/linux/x86_64/gtk3_unofficial_branding.mozconfig
+CONFIGURE_ARGS+=       --enable-optimize=-O3
+CONFIGURE_ARGS+=       --enable-application=basilisk
+CONFIGURE_ARGS+=       --enable-devtools
+CONFIGURE_ARGS+=       --enable-av1
+CONFIGURE_ARGS+=       --enable-jxl
+CONFIGURE_ARGS+=       --enable-pie
+CONFIGURE_ARGS+=       --disable-tests
+CONFIGURE_ARGS+=       --disable-gamepad       # non-default
+CONFIGURE_ARGS+=       --disable-debug
+CONFIGURE_ARGS+=       --disable-necko-wifi
+CONFIGURE_ARGS+=       --disable-updater
+CONFIGURE_ARGS+=       --with-pthreads
+CONFIGURE_ARGS+=       --disable-gconf
+# unlike palemoon/firefox, basilisk *only* has "unofficial branding"
+CONFIGURE_ARGS+=       --disable-official-branding
+
+# non-default: causes build failures on NetBSD
+CONFIGURE_ARGS+=       --disable-precompiled-startupcache
+
+# non-default: do not override system memory allocator
+CONFIGURE_ARGS+=       --disable-jemalloc
+
+# non-default options to integrate better with pkgsrc
+# do not use system cairo, causes segfaults
+CONFIGURE_ARGS+=       --prefix=${PREFIX}
+CONFIGURE_ARGS+=       --with-system-bz2=${BUILDLINK_PREFIX.bzip2}
+CONFIGURE_ARGS+=       --with-system-zlib
+
+.include "../../mk/bsd.prefs.mk"
+
+.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "x86_64"
+TOOL_DEPENDS+=         yasm>=1.1:../../devel/yasm
+.endif
+
+.if ${MACHINE_PLATFORM:MNetBSD-*-earm*}
+LDFLAGS+=              -Wl,--no-keep-memory
+.endif
+
+PLIST_VARS+=           ffvpx
+
+.if ${MACHINE_ARCH} == "x86_64"
+PLIST.ffvpx=           yes     # see platform/old-configure.in
+.endif
+
+SUBST_CLASSES+=                desktop
+SUBST_STAGE.desktop=   pre-configure
+SUBST_FILES.desktop=   platform/toolkit/mozapps/installer/linux/rpm/mozilla.desktop
+SUBST_SED.desktop=     -e 's,@MOZ_APP_DISPLAYNAME@,Basilisk,g'
+SUBST_SED.desktop+=    -e 's,@MOZ_APP_NAME@,basilisk,g'
+
+INSTALLATION_DIRS+=    share/applications
+INSTALLATION_DIRS+=    share/icons/hicolor/16x16/apps
+INSTALLATION_DIRS+=    share/icons/hicolor/32x32/apps
+INSTALLATION_DIRS+=    share/icons/hicolor/48x48/apps
+INSTALLATION_DIRS+=    share/icons/hicolor/128x128/apps
+
+CHECK_PORTABILITY_SKIP+=       platform/js/src/tests/*.sh
+CHECK_PORTABILITY_SKIP+=       platform/memory/jemalloc/src/configure
+CHECK_PORTABILITY_SKIP+=       platform/security/nss/tests/*/*.sh
+
+PYTHON_VERSIONS_ACCEPTED=      27
+PYTHON_FOR_BUILD_ONLY=         tool
+
+pre-configure:
+       ${MKDIR} ${CONFIGURE_DIRS}
+       cd ${WRKSRC} && autoconf-2.13
+       cd ${WRKSRC}/basilisk && autoconf-2.13
+       cd ${WRKSRC}/platform/js/src && autoconf-2.13
+
+pre-patch:
+       ${MV} ${WRKDIR}/uxp/* ${WRKSRC}/platform/
+       ${RM} -rf ${WRKSRC}/platform/python/psutil
+       ${MV} ${WRKDIR}/psutil-3.4.2 ${WRKSRC}/platform/python/psutil
+
+pre-build:
+       ${TOUCH} ${WRKSRC}/platform/configure
+       ${TOUCH} ${WRKDIR}/build/config.status
+
+post-install:
+       ${FIND} ${DESTDIR}${PREFIX} -name '*.a' -exec ${RM} '{}' ';'
+       ${RM} -rf ${DESTDIR}${PREFIX}/include
+       ${RM} -rf ${DESTDIR}${PREFIX}/share/idl
+       ${RM} -rf ${DESTDIR}${PREFIX}/lib/*-devel*
+       ${RM} -rf ${DESTDIR}${PREFIX}/lib/basilisk-devel-${PKGVERSION_NOREV}
+       ${INSTALL_DATA} ${WRKSRC}/basilisk/branding/unofficial/default16.png \
+           ${DESTDIR}${PREFIX}/share/icons/hicolor/16x16/apps/basilisk.png
+       ${INSTALL_DATA} ${WRKSRC}/basilisk/branding/unofficial/default32.png \
+           ${DESTDIR}${PREFIX}/share/icons/hicolor/32x32/apps/basilisk.png
+       ${INSTALL_DATA} ${WRKSRC}/basilisk/branding/unofficial/default48.png \
+           ${DESTDIR}${PREFIX}/share/icons/hicolor/48x48/apps/basilisk.png
+       ${INSTALL_DATA} ${WRKSRC}/basilisk/branding/unofficial/mozicon128.png \
+           ${DESTDIR}${PREFIX}/share/icons/hicolor/128x128/apps/basilisk.png
+       ${INSTALL_DATA} ${WRKSRC}/platform/toolkit/mozapps/installer/linux/rpm/mozilla.desktop \
+           ${DESTDIR}${PREFIX}/share/applications/basilisk.desktop
+
+.include "options.mk"
+.include "../../archivers/bzip2/buildlink3.mk"
+.if ${OPSYS} == "Linux"
+.  include "../../audio/alsa-lib/buildlink3.mk"
+.endif
+.include "../../devel/zlib/buildlink3.mk"
+.include "../../graphics/hicolor-icon-theme/buildlink3.mk"
+.include "../../lang/python/batteries-included.mk"
+.include "../../lang/python/application.mk"
+.include "../../lang/python/tool.mk"
+.include "../../multimedia/ffmpeg6/buildlink3.mk"
+.include "../../security/openssl/buildlink3.mk"
+.include "../../sysutils/desktop-file-utils/desktopdb.mk"
+.if ${OPSYS} == "Darwin"
+CONFIGURE_ARGS+=       --enable-default-toolkit=cairo-cocoa
+.else
+CONFIGURE_ARGS+=       --enable-default-toolkit=cairo-gtk3
+.  include "../../x11/gtk2/buildlink3.mk"
+.  include "../../x11/gtk3/buildlink3.mk"
+.  include "../../x11/libXt/buildlink3.mk"
+.endif
+.include "../../mk/atomic64.mk"
+.include "../../mk/bsd.pkg.mk"
Index: pkgsrc/www/basilisk/PLIST
diff -u /dev/null pkgsrc/www/basilisk/PLIST:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/PLIST   Fri Apr 25 21:25:03 2025
@@ -0,0 +1,49 @@
+@comment $NetBSD: PLIST,v 1.1 2025/04/25 21:25:03 nia Exp $
+bin/basilisk
+lib/basilisk-52.9.0/application.ini
+lib/basilisk-52.9.0/basilisk
+lib/basilisk-52.9.0/basilisk-bin
+lib/basilisk-52.9.0/browser/blocklist.xml
+lib/basilisk-52.9.0/browser/chrome.manifest
+lib/basilisk-52.9.0/browser/chrome/icons/default/default16.png
+lib/basilisk-52.9.0/browser/chrome/icons/default/default32.png
+lib/basilisk-52.9.0/browser/chrome/icons/default/default48.png
+lib/basilisk-52.9.0/browser/components/components.manifest
+lib/basilisk-52.9.0/browser/components/libbrowsercomps.so
+lib/basilisk-52.9.0/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}.xpi
+lib/basilisk-52.9.0/browser/icons/mozicon128.png
+lib/basilisk-52.9.0/browser/omni.ja
+lib/basilisk-52.9.0/chrome.manifest
+lib/basilisk-52.9.0/defaults/pref/channel-prefs.js
+lib/basilisk-52.9.0/dependentlibs.list
+lib/basilisk-52.9.0/dictionaries/en-US.aff
+lib/basilisk-52.9.0/dictionaries/en-US.dic
+lib/basilisk-52.9.0/fonts/TwemojiMozilla.ttf
+lib/basilisk-52.9.0/gtk2/libmozgtk.so
+lib/basilisk-52.9.0/icudt63l.dat
+lib/basilisk-52.9.0/libhunspell.so
+lib/basilisk-52.9.0/liblgpllibs.so
+${PLIST.ffvpx}lib/basilisk-52.9.0/libmozavcodec.so
+${PLIST.ffvpx}lib/basilisk-52.9.0/libmozavutil.so
+lib/basilisk-52.9.0/libmozgtk.so
+lib/basilisk-52.9.0/libmozsqlite3.so
+lib/basilisk-52.9.0/libnspr4.so
+lib/basilisk-52.9.0/libnss3.so
+lib/basilisk-52.9.0/libnssckbi.so
+lib/basilisk-52.9.0/libnssutil3.so
+lib/basilisk-52.9.0/libplc4.so
+lib/basilisk-52.9.0/libplds4.so
+lib/basilisk-52.9.0/libsmime3.so
+lib/basilisk-52.9.0/libsoftokn3.so
+lib/basilisk-52.9.0/libssl3.so
+lib/basilisk-52.9.0/libxul.so
+lib/basilisk-52.9.0/omni.ja
+lib/basilisk-52.9.0/platform.ini
+lib/basilisk-52.9.0/plugin-container
+lib/basilisk-52.9.0/removed-files
+lib/basilisk-52.9.0/run-mozilla.sh
+share/applications/basilisk.desktop
+share/icons/hicolor/128x128/apps/basilisk.png
+share/icons/hicolor/16x16/apps/basilisk.png
+share/icons/hicolor/32x32/apps/basilisk.png
+share/icons/hicolor/48x48/apps/basilisk.png
Index: pkgsrc/www/basilisk/PLIST.Linux
diff -u /dev/null pkgsrc/www/basilisk/PLIST.Linux:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/PLIST.Linux     Fri Apr 25 21:25:03 2025
@@ -0,0 +1,2 @@
+@comment $NetBSD: PLIST.Linux,v 1.1 2025/04/25 21:25:03 nia Exp $
+lib/basilisk-52.9.0/libfreeblpriv3.so
Index: pkgsrc/www/basilisk/PLIST.NetBSD
diff -u /dev/null pkgsrc/www/basilisk/PLIST.NetBSD:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/PLIST.NetBSD    Fri Apr 25 21:25:03 2025
@@ -0,0 +1,2 @@
+@comment $NetBSD: PLIST.NetBSD,v 1.1 2025/04/25 21:25:03 nia Exp $
+lib/basilisk-52.9.0/libfreebl3.so
Index: pkgsrc/www/basilisk/distinfo
diff -u /dev/null pkgsrc/www/basilisk/distinfo:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/distinfo        Fri Apr 25 21:25:03 2025
@@ -0,0 +1,34 @@
+$NetBSD: distinfo,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+BLAKE2s (basilisk-2025.04.23/basilisk.tar.gz) = 8049ef38576e0b083f55e2a1b4472483213a804eaed4a539aebc29e59faf5578
+SHA512 (basilisk-2025.04.23/basilisk.tar.gz) = c850e0178b89816d4ab2ea02323c563e5a62c0f60d6251598f9b6334be14ff9c54f524f4ca0d370807ab638e660c4d6456e468112dc3b25c2e50ffb9bd97317b
+Size (basilisk-2025.04.23/basilisk.tar.gz) = 12923056 bytes
+BLAKE2s (basilisk-2025.04.23/psutil.tar.gz) = 7a2c5c938910795453cf1cdfd5fbfa4dc8cac15e6eb43a5e9aba91ac032b37ce
+SHA512 (basilisk-2025.04.23/psutil.tar.gz) = 95c246ed4ce68a476f83868312101d88dafa9d4cef96ff60af646a443c00e6cc447d37cc1ac4e85224db16c24390575174bb7ef76f48cb839fe2e93749107ffb
+Size (basilisk-2025.04.23/psutil.tar.gz) = 274361 bytes
+BLAKE2s (basilisk-2025.04.23/uxp.tar.gz) = 1e7878775dec45e36d53b64904d4aa4642847b114436307cfe99c840880d7306
+SHA512 (basilisk-2025.04.23/uxp.tar.gz) = 804122497f184505e1bc1c6b86695788b6dcfefbdd0dc9903bfc244e82dc66d9b8de6569f2dd5331f64b20979936f764c560bd3ee39875f0708d840f28aa749c
+Size (basilisk-2025.04.23/uxp.tar.gz) = 264519296 bytes
+SHA1 (patch-platform_build_moz.build) = 7b45929d58ad0963423f7c859922df6d98413c67
+SHA1 (patch-platform_gfx_angle_src_libANGLE_renderer_gl_glx_FunctionsGLX.cpp) = 502d79eb3ef41e08328bbac9fbb5048b96660bbb
+SHA1 (patch-platform_intl_icu_source_configure) = 87d19e9212b4340d9b052b5a89be84432ad1cff2
+SHA1 (patch-platform_ipc_chromium_src_base_atomicops.h) = ab4b489e9f9c22a861a275924ef34a909d210828
+SHA1 (patch-platform_ipc_chromium_src_base_atomicops__internals__arm__gcc.h) = f33b6c391689c52d0a6855e29ff25d863a7f15e5
+SHA1 (patch-platform_media_libaom_config_linux_arm_config_aom__config.h) = 69ef22fe9892c2288accb6eb00b4533d8cee0299
+SHA1 (patch-platform_media_libcubeb_src_cubeb__sun.c) = ce27774d772d65fa60b6be5bee82fbe4f787f3d1
+SHA1 (patch-platform_media_libtheora_moz.build) = a7bad662dabb87c6a85542a4a50f8ed693064bc6
+SHA1 (patch-platform_media_libvpx_config_linux_arm_vpx__config.h) = a580208cd342d7dc27985118e1707772e0cccf02
+SHA1 (patch-platform_media_webrtc_trunk_webrtc_modules_audio__device_audio__device.gypi) = b673eeaf3c2e08428870e5a2d06dfae3f6e7752e
+SHA1 (patch-platform_netwerk_srtp_src_crypto_hash_hmac.c) = 59f8b8756f5486b59c88fac8901b80c0fbc1485f
+SHA1 (patch-platform_netwerk_srtp_src_crypto_kernel_crypto__kernel.c) = b486d5d0e2b9878d32c655f1f86a5d6535b7da85
+SHA1 (patch-platform_nsprpub_pr_include_md__netbsd.cfg) = 1dc06ad2dc49eb3297dc0651dce546cff6882f7b
+SHA1 (patch-platform_nsprpub_pr_include_md__netbsd.h) = 72de23f42dc38d9cfacf41776e53af613a0c4f19
+SHA1 (patch-platform_nsprpub_pr_include_private_pprthred.h) = eeee6714ba27e6465701bffbc404915ceb0c9e55
+SHA1 (patch-platform_nsprpub_pr_src_pthreads_ptsynch.c) = f99271490a983d0a1d101cb0d2b593a3987549d7
+SHA1 (patch-platform_nsprpub_pr_src_pthreads_ptthread.c) = a04b06e39c289ac32dfbb6cbd79b1d7ecf0b560d
+SHA1 (patch-platform_security_generate__mapfile.py) = ae457a8e85c4ce95014dff442b8afd0e20ded543
+SHA1 (patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops.h) = 73b57772d29b0567c0aa1faea8a3f345dbc0488a
+SHA1 (patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops__internals__arm__gcc.h) = 2a5ccc95fb5860b1be97947f3aee8307f4a25bc1
+SHA1 (patch-platform_toolkit_xre_nsX11ErrorHandler.cpp) = 164d93a5b1aaeba15b524fdaef0483b4a9400ac1
+SHA1 (patch-platform_xpcom_reflect_xptcall_md_unix_xptcinvoke__arm__netbsd.cpp) = 5b6a5c6eea2668cc5eaaf775400c382114876d86
+SHA1 (patch-platform_xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp) = de7188f7ac09fd3d4a65968a12ae324b3a0415c4
Index: pkgsrc/www/basilisk/hacks.mk
diff -u /dev/null pkgsrc/www/basilisk/hacks.mk:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/hacks.mk        Fri Apr 25 21:25:03 2025
@@ -0,0 +1,15 @@
+# $NetBSD: hacks.mk,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+.if !defined(PALEMOON_HACKS_MK)
+PALEMOON_HACKS_MK=     # defined
+
+### [Sat Aug  3 11:00:17 CEST 2024 : nia]
+### NetBSD 9.x does not expose all standard C++ functions with default
+### source visibility.
+###
+.if ${OPSYS} == "NetBSD" && ${OPSYS_VERSION} < 100000
+PKG_HACKS+=            netbsd-source
+CXXFLAGS+=             -D_NETBSD_SOURCE
+.endif
+
+.endif
Index: pkgsrc/www/basilisk/options.mk
diff -u /dev/null pkgsrc/www/basilisk/options.mk:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/options.mk      Fri Apr 25 21:25:03 2025
@@ -0,0 +1,29 @@
+# $NetBSD: options.mk,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+PKG_OPTIONS_VAR=               PKG_OPTIONS.basilisk
+PKG_SUPPORTED_OPTIONS=         dbus pulseaudio webrtc
+#PKG_SUGGESTED_OPTIONS.NetBSD= webrtc
+#PKG_SUGGESTED_OPTIONS.Linux=  webrtc
+
+.include "../../mk/bsd.options.mk"
+
+.if !empty(PKG_OPTIONS:Mdbus)
+CONFIGURE_ARGS+=       --enable-dbus
+.  include "../../sysutils/dbus/buildlink3.mk"
+.else
+CONFIGURE_ARGS+=       --disable-dbus
+.endif
+
+.if !empty(PKG_OPTIONS:Mpulseaudio)
+CONFIGURE_ARGS+=       --enable-pulseaudio
+.  include "../../audio/pulseaudio/buildlink3.mk"
+.else
+CONFIGURE_ARGS+=       --disable-pulseaudio
+.endif
+
+.if !empty(PKG_OPTIONS:Mwebrtc)
+CONFIGURE_ARGS+=       --enable-webrtc
+.  include "../../graphics/libv4l/buildlink3.mk"
+.else
+CONFIGURE_ARGS+=       --disable-webrtc
+.endif

Index: pkgsrc/www/basilisk/patches/patch-platform_build_moz.build
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_build_moz.build:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_build_moz.build  Fri Apr 25 21:25:03 2025
@@ -0,0 +1,29 @@
+$NetBSD: patch-platform_build_moz.build,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Avoid configure errors.
+
+--- platform/build/moz.build.orig      2024-07-25 09:37:43.581267584 +0000
++++ platform/build/moz.build
+@@ -52,12 +52,6 @@ if CONFIG['ENABLE_TESTS']:
+     if CONFIG['OS_ARCH'] == 'Linux':
+         FINAL_TARGET_FILES += ['/tools/rb/fix_linux_stack.py']
+ 
+-# Put a useful .gdbinit in the bin directory, to be picked up automatically
+-# by GDB when we debug executables there.
+-FINAL_TARGET_FILES += ['/.gdbinit']
+-FINAL_TARGET_PP_FILES += ['.gdbinit_python.in']
+-OBJDIR_FILES += ['!/dist/bin/.gdbinit_python']
+-
+ # Install the clang runtime library for ASAN next to the binaries we produce.
+ if CONFIG['MOZ_ASAN'] and CONFIG['MOZ_CLANG_RT_ASAN_LIB_PATH']:
+     FINAL_TARGET_FILES += [CONFIG['MOZ_CLANG_RT_ASAN_LIB_PATH']]
+@@ -78,9 +72,6 @@ if CONFIG['MOZ_APP_BASENAME']:
+ DEFINES['TOPSRCDIR'] = TOPSRCDIR
+ DEFINES['TOPOBJDIR'] = TOPOBJDIR
+ 
+-# NOTE: Keep .gdbinit in the topsrcdir for people who run gdb from the topsrcdir.
+-OBJDIR_FILES += ['/.gdbinit']
+-
+ # Put a .lldbinit in the bin directory and the objdir, to be picked up
+ # automatically by LLDB when we debug executables using either of those two
+ # directories as the current working directory.  The .lldbinit file will
Index: pkgsrc/www/basilisk/patches/patch-platform_gfx_angle_src_libANGLE_renderer_gl_glx_FunctionsGLX.cpp
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_gfx_angle_src_libANGLE_renderer_gl_glx_FunctionsGLX.cpp:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_gfx_angle_src_libANGLE_renderer_gl_glx_FunctionsGLX.cpp  Fri Apr 25 21:25:03 2025
@@ -0,0 +1,18 @@
+$NetBSD: patch-platform_gfx_angle_src_libANGLE_renderer_gl_glx_FunctionsGLX.cpp,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+NetBSD also does not have the libGL.so.1 version.
+
+--- platform/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp.orig      2024-07-25 22:12:46.396663262 +0000
++++ platform/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
+@@ -130,7 +130,11 @@ bool FunctionsGLX::initialize(Display *x
+     // which a GLXWindow was ever created.
+     if (!sLibHandle)
+     {
++#if defined(__NetBSD__) || defined(__OpenBSD__)
++        sLibHandle = dlopen("libGL.so", RTLD_NOW);
++#else
+         sLibHandle = dlopen("libGL.so.1", RTLD_NOW);
++#endif
+         if (!sLibHandle)
+         {
+             *errorString = std::string("Could not dlopen libGL.so.1: ") + dlerror();
Index: pkgsrc/www/basilisk/patches/patch-platform_intl_icu_source_configure
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_intl_icu_source_configure:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_intl_icu_source_configure        Fri Apr 25 21:25:03 2025
@@ -0,0 +1,22 @@
+$NetBSD: patch-platform_intl_icu_source_configure,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Shell portability.
+
+--- platform/intl/icu/source/configure.orig    2024-07-10 08:54:53.000000000 +0000
++++ platform/intl/icu/source/configure
+@@ -7867,13 +7867,13 @@ fi
+ # Now that we're done using CPPFLAGS etc. for tests, we can change it
+ # for build.
+ 
+-if test "${CC}" == "clang"; then
++if test "${CC}" = "clang"; then
+    CLANGCFLAGS="-Qunused-arguments -Wno-parentheses-equality"
+ else
+    CLANGCFLAGS=""
+ fi
+ 
+-if test "${CXX}" == "clang++"; then
++if test "${CXX}" = "clang++"; then
+    CLANGCXXFLAGS="-Qunused-arguments -Wno-parentheses-equality"
+ else
+    CLANGCXXFLAGS=""
Index: pkgsrc/www/basilisk/patches/patch-platform_ipc_chromium_src_base_atomicops.h
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_ipc_chromium_src_base_atomicops.h:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_ipc_chromium_src_base_atomicops.h        Fri Apr 25 21:25:03 2025
@@ -0,0 +1,15 @@
+$NetBSD: patch-platform_ipc_chromium_src_base_atomicops.h,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Fixes for NetBSD/arm, taken from www/firefox52
+
+--- platform/ipc/chromium/src/base/atomicops.h.orig    2024-07-10 08:54:53.000000000 +0000
++++ platform/ipc/chromium/src/base/atomicops.h
+@@ -46,7 +46,7 @@ typedef int64_t Atomic64;
+ 
+ // Use AtomicWord for a machine-sized pointer.  It will use the Atomic32 or
+ // Atomic64 routines below, depending on your architecture.
+-#ifdef OS_OPENBSD
++#if defined(OS_OPENBSD) || (defined(OS_NETBSD) && defined(ARCH_CPU_ARM_FAMILY))
+ #ifdef ARCH_CPU_64_BITS
+ typedef Atomic64 AtomicWord;
+ #else
Index: pkgsrc/www/basilisk/patches/patch-platform_ipc_chromium_src_base_atomicops__internals__arm__gcc.h
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_ipc_chromium_src_base_atomicops__internals__arm__gcc.h:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_ipc_chromium_src_base_atomicops__internals__arm__gcc.h   Fri Apr 25 21:25:03 2025
@@ -0,0 +1,92 @@
+$NetBSD: patch-platform_ipc_chromium_src_base_atomicops__internals__arm__gcc.h,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Fixes for NetBSD/arm, taken from www/firefox52
+
+--- platform/ipc/chromium/src/base/atomicops_internals_arm_gcc.h.orig  2024-07-10 08:54:53.000000000 +0000
++++ platform/ipc/chromium/src/base/atomicops_internals_arm_gcc.h
+@@ -13,44 +13,19 @@
+ namespace base {
+ namespace subtle {
+ 
+-// 0xffff0fc0 is the hard coded address of a function provided by
+-// the kernel which implements an atomic compare-exchange. On older
+-// ARM architecture revisions (pre-v6) this may be implemented using
+-// a syscall. This address is stable, and in active use (hard coded)
+-// by at least glibc-2.7 and the Android C library.
+-typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value,
+-                                           Atomic32 new_value,
+-                                           volatile Atomic32* ptr);
+-LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) =
+-    (LinuxKernelCmpxchgFunc) 0xffff0fc0;
+-
+-typedef void (*LinuxKernelMemoryBarrierFunc)(void);
+-LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) =
+-    (LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
+-
+-
+ inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                          Atomic32 old_value,
+                                          Atomic32 new_value) {
+-  Atomic32 prev_value = *ptr;
+-  do {
+-    if (!pLinuxKernelCmpxchg(old_value, new_value,
+-                             const_cast<Atomic32*>(ptr))) {
+-      return old_value;
+-    }
+-    prev_value = *ptr;
+-  } while (prev_value == old_value);
+-  return prev_value;
++  return __sync_val_compare_and_swap(ptr, old_value, new_value);
+ }
+ 
+ inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                          Atomic32 new_value) {
+-  Atomic32 old_value;
++  Atomic32 prev_value;
+   do {
+-    old_value = *ptr;
+-  } while (pLinuxKernelCmpxchg(old_value, new_value,
+-                               const_cast<Atomic32*>(ptr)));
+-  return old_value;
++    prev_value = *ptr;
++  } while (!__sync_bool_compare_and_swap(ptr, prev_value, new_value));
++  return prev_value;
+ }
+ 
+ inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+@@ -60,18 +35,15 @@ inline Atomic32 NoBarrier_AtomicIncremen
+ 
+ inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                         Atomic32 increment) {
+-  for (;;) {
+-    // Atomic exchange the old value with an incremented one.
+-    Atomic32 old_value = *ptr;
+-    Atomic32 new_value = old_value + increment;
+-    if (pLinuxKernelCmpxchg(old_value, new_value,
+-                            const_cast<Atomic32*>(ptr)) == 0) {
+-      // The exchange took place as expected.
+-      return new_value;
+-    }
+-    // Otherwise, *ptr changed mid-loop and we need to retry.
+-  }
++  Atomic32 old_value;
++  Atomic32 new_value;
+ 
++  do {
++    // Atomic exchange the old value with an incremented one.
++    old_value = *ptr;
++    new_value = old_value + increment;
++  } while (!__sync_bool_compare_and_swap(ptr, old_value, new_value));
++  return new_value;
+ }
+ 
+ inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+@@ -91,7 +63,7 @@ inline void NoBarrier_Store(volatile Ato
+ }
+ 
+ inline void MemoryBarrier() {
+-  pLinuxKernelMemoryBarrier();
++  __sync_synchronize();
+ }
+ 
+ inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
Index: pkgsrc/www/basilisk/patches/patch-platform_media_libaom_config_linux_arm_config_aom__config.h
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_media_libaom_config_linux_arm_config_aom__config.h:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_media_libaom_config_linux_arm_config_aom__config.h       Fri Apr 25 21:25:03 2025
@@ -0,0 +1,19 @@
+$NetBSD: patch-platform_media_libaom_config_linux_arm_config_aom__config.h,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Runtime CPU detection on ARM is currently unimplemented for anything
+except Linux.
+
+--- platform/media/libaom/config/linux/arm/config/aom_config.h.orig    2024-07-29 11:09:32.665087168 +0000
++++ platform/media/libaom/config/linux/arm/config/aom_config.h
+@@ -59,7 +59,11 @@
+ #define CONFIG_RD_DEBUG 0
+ #define CONFIG_REALTIME_ONLY 0
+ #define CONFIG_RT_ML_PARTITIONING 0
++#ifdef __linux
+ #define CONFIG_RUNTIME_CPU_DETECT 1
++#else
++#define CONFIG_RUNTIME_CPU_DETECT 0
++#endif
+ #define CONFIG_SHARED 0
+ #define CONFIG_SIZE_LIMIT 0
+ #define CONFIG_SPATIAL_RESAMPLING 1
Index: pkgsrc/www/basilisk/patches/patch-platform_media_libcubeb_src_cubeb__sun.c
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_media_libcubeb_src_cubeb__sun.c:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_media_libcubeb_src_cubeb__sun.c  Fri Apr 25 21:25:03 2025
@@ -0,0 +1,1134 @@
+$NetBSD: patch-platform_media_libcubeb_src_cubeb__sun.c,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Replace with modern version of the driver from current-ish firefox.
+
+Fixes playback artifacts on NetBSD.
+
+--- platform/media/libcubeb/src/cubeb_sun.c.orig       2024-07-25 20:59:35.023700095 +0000
++++ platform/media/libcubeb/src/cubeb_sun.c
+@@ -1,81 +1,74 @@
+ /*
+- * Copyright (c) 2013, 2017 Ginn Chen <ginnchen%gmail.com@localhost>
++ * Copyright © 2019-2024 Nia Alarie
+  *
+  * This program is made available under an ISC-style license.  See the
+  * accompanying file LICENSE for details.
+  */
+-#include <poll.h>
++#include <sys/audioio.h>
++#include <sys/ioctl.h>
++#include <fcntl.h>
++#include <unistd.h>
+ #include <pthread.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+-#include <errno.h>
+-#include <fcntl.h>
+-#include <sys/audio.h>
+-#include <sys/stat.h>
+-#include <unistd.h>
+-#include <sys/stropts.h>
++#include <string.h>
++#include <math.h>
+ #include "cubeb/cubeb.h"
+ #include "cubeb-internal.h"
+ 
+-/* Macros copied from audio_oss.h */
+-/*
+- * CDDL HEADER START
+- *
+- * The contents of this file are subject to the terms of the
+- * Common Development and Distribution License (the "License").
+- * You may not use this file except in compliance with the License.
+- *
+- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+- * or http://www.opensolaris.org/os/licensing.
+- * See the License for the specific language governing permissions
+- * and limitations under the License.
+- *
+- * When distributing Covered Code, include this CDDL HEADER in each
+- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+- * If applicable, add the following below this CDDL HEADER, with the
+- * fields enclosed by brackets "[]" replaced with your own identifying
+- * information: Portions Copyright [yyyy] [name of copyright owner]
+- *
+- * CDDL HEADER END
+- */
++#define CUBEB_OLD_API /* seamonkey and older firefox */
++
++#define BYTES_TO_FRAMES(bytes, channels) \
++  (bytes / (channels * sizeof(int16_t)))
++
++#define FRAMES_TO_BYTES(frames, channels) \
++  (frames * (channels * sizeof(int16_t)))
++
++/* Default to 4 + 1 for the default device. */
++#ifndef SUN_DEVICE_COUNT
++#define SUN_DEVICE_COUNT (5)
++#endif
++
++/* Supported well by most hardware. */
++#ifndef SUN_PREFER_RATE
++#define SUN_PREFER_RATE (48000)
++#endif
++
++/* Standard acceptable minimum. */
++#ifndef SUN_LATENCY_MS
++#define SUN_LATENCY_MS (40)
++#endif
++
++#ifndef SUN_DEFAULT_DEVICE
++#define SUN_DEFAULT_DEVICE "/dev/audio"
++#endif
++
++#ifndef SUN_POLL_TIMEOUT
++#define SUN_POLL_TIMEOUT (1000)
++#endif
++
++#ifndef SUN_BUFFER_FRAMES
++#define SUN_BUFFER_FRAMES (32)
++#endif
++
+ /*
+- * Copyright (C) 4Front Technologies 1996-2008.
+- *
+- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+- * Use is subject to license terms.
++ * Supported on NetBSD regardless of hardware.
+  */
+-#define OSSIOCPARM_MASK 0x1fff          /* parameters must be < 8192 bytes */
+-#define OSSIOC_VOID     0x00000000      /* no parameters */
+-#define OSSIOC_OUT      0x20000000      /* copy out parameters */
+-#define OSSIOC_IN       0x40000000      /* copy in parameters */
+-#define OSSIOC_INOUT    (OSSIOC_IN|OSSIOC_OUT)
+-#define OSSIOC_SZ(t)    ((sizeof (t) & OSSIOCPARM_MASK) << 16)
+-#define __OSSIO(x, y)           ((int)(OSSIOC_VOID|(x<<8)|y))
+-#define __OSSIOR(x, y, t)       ((int)(OSSIOC_OUT|OSSIOC_SZ(t)|(x<<8)|y))
+-#define __OSSIOWR(x, y, t)      ((int)(OSSIOC_INOUT|OSSIOC_SZ(t)|(x<<8)|y))
+-#define SNDCTL_DSP_SPEED        __OSSIOWR('P', 2, int)
+-#define SNDCTL_DSP_CHANNELS     __OSSIOWR('P', 6, int)
+-#define SNDCTL_DSP_SETFMT       __OSSIOWR('P', 5, int)  /* Selects ONE fmt */
+-#define SNDCTL_DSP_GETODELAY    __OSSIOR('P', 23, int)
+-#define SNDCTL_DSP_HALT_OUTPUT  __OSSIO('P', 34)
+-#define AFMT_S16_LE     0x00000010
+-#define AFMT_S16_BE     0x00000020
+ 
+-#if defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__)
+-#define AFMT_S16_NE    AFMT_S16_BE
+-#else
+-#define AFMT_S16_NE    AFMT_S16_LE
++#ifndef SUN_MAX_CHANNELS
++# ifdef __NetBSD__
++#  define SUN_MAX_CHANNELS (12)
++# else
++#  define SUN_MAX_CHANNELS (2)
++# endif
+ #endif
+ 
+-#define DEFAULT_AUDIO_DEVICE "/dev/audio"
+-#define DEFAULT_DSP_DEVICE   "/dev/dsp"
+-
+-#define BUF_SIZE_MS 10
++#ifndef SUN_MIN_RATE
++#define SUN_MIN_RATE (1000)
++#endif
+ 
+-#if defined(CUBEB_SUNAUDIO_DEBUG)
+-#define DPR(...) fprintf(stderr, __VA_ARGS__);
+-#else
+-#define DPR(...) do {} while(0)
++#ifndef SUN_MAX_RATE
++#define SUN_MAX_RATE (192000)
+ #endif
+ 
+ static struct cubeb_ops const sunaudio_ops;
+@@ -85,420 +78,680 @@ struct cubeb {
+ };
+ 
+ struct cubeb_stream {
+-  cubeb * context;
+-  pthread_t th;                         /* to run real-time audio i/o */
+-  pthread_mutex_t mutex;        /* protects fd and frm_played */
+-  int fd;                       /* link us to sunaudio */
+-  int active;                   /* cubec_start() called */
+-  int conv;                     /* need float->s16 conversion */
+-  int using_oss;
+-  unsigned char *buf;           /* data is prepared here */
+-  unsigned int rate;
+-  unsigned int n_channles;
+-  unsigned int bytes_per_ch;
+-  unsigned int n_frm;
+-  unsigned int buffer_size;
+-  int64_t frm_played;
+-  cubeb_data_callback data_cb;    /* cb to preapare data */
+-  cubeb_state_callback state_cb;  /* cb to notify about state changes */
+-  void *arg;                    /* user arg to {data,state}_cb */
++  struct cubeb * context;
++  void * user_ptr;
++  pthread_t thread;
++  pthread_mutex_t mutex; /* protects running, volume, frames_written */
++  int floating;
++  int running;
++  int play_fd;
++  int record_fd;
++  float volume;
++  struct audio_info p_info; /* info for the play fd */
++  struct audio_info r_info; /* info for the record fd */
++  cubeb_data_callback data_cb;
++  cubeb_state_callback state_cb;
++  int16_t * play_buf;
++  int16_t * record_buf;
++  float * f_play_buf;
++  float * f_record_buf;
++  char input_name[32];
++  char output_name[32];
++  uint64_t frames_written;
++  uint64_t blocks_written;
+ };
+ 
++int
++sunaudio_init(cubeb ** context, char const * context_name)
++{
++  cubeb * c;
++
++  (void)context_name;
++  if ((c = calloc(1, sizeof(cubeb))) == NULL) {
++    return CUBEB_ERROR;
++  }
++  c->ops = &sunaudio_ops;
++  *context = c;
++  return CUBEB_OK;
++}
++
+ static void
+-float_to_s16(void *ptr, long nsamp)
++sunaudio_destroy(cubeb * context)
+ {
+-  int16_t *dst = ptr;
+-  float *src = ptr;
++  free(context);
++}
+ 
+-  while (nsamp-- > 0)
+-    *(dst++) = *(src++) * 32767;
++static char const *
++sunaudio_get_backend_id(cubeb * context)
++{
++  return "sun";
+ }
+ 
+-static void *
+-sunaudio_mainloop(void *arg)
++static int
++sunaudio_get_preferred_sample_rate(cubeb * context, uint32_t * rate)
+ {
+-  struct cubeb_stream *s = arg;
+-  int state;
++  (void)context;
+ 
+-  DPR("sunaudio_mainloop()\n");
++  *rate = SUN_PREFER_RATE;
++  return CUBEB_OK;
++}
+ 
+-  s->state_cb(s, s->arg, CUBEB_STATE_STARTED);
++static int
++sunaudio_get_max_channel_count(cubeb * context, uint32_t * max_channels)
++{
++  (void)context;
+ 
+-  pthread_mutex_lock(&s->mutex);
+-  DPR("sunaudio_mainloop(), started\n");
++  *max_channels = SUN_MAX_CHANNELS;
++  return CUBEB_OK;
++}
+ 
+-  for (;;) {
+-    if (!s->active) {
+-      DPR("sunaudio_mainloop() stopped\n");
+-      state = CUBEB_STATE_STOPPED;
+-      break;
+-    }
++static int
++sunaudio_get_min_latency(cubeb * context, cubeb_stream_params params,
++                    uint32_t * latency_frames)
++{
++  (void)context;
+ 
+-    if (!s->using_oss) {
+-      audio_info_t info;
+-      ioctl(s->fd, AUDIO_GETINFO, &info);
+-      if (s->frm_played > info.play.samples + 3 * s->n_frm) {
+-        pthread_mutex_unlock(&s->mutex);
+-        struct timespec ts = {0, 10000}; // 10 ms
+-        nanosleep(&ts, NULL);
+-        pthread_mutex_lock(&s->mutex);
+-        continue;
+-      }
+-    }
++  *latency_frames = SUN_LATENCY_MS * params.rate / 1000;
++  return CUBEB_OK;
++}
+ 
+-    pthread_mutex_unlock(&s->mutex);
+-    unsigned int got = s->data_cb(s, s->arg, NULL, s->buf, s->n_frm);
+-    DPR("sunaudio_mainloop() ask %d got %d\n", s->n_frm, got);
+-    pthread_mutex_lock(&s->mutex);
++static int
++sunaudio_get_hwinfo(const char * device, struct audio_info * format,
++               int * props, struct audio_device * dev)
++{
++  int fd = -1;
+ 
+-    if (got < 0) {
+-      DPR("sunaudio_mainloop() cb err\n");
+-      state = CUBEB_STATE_ERROR;
+-      break;
+-    }
++  if ((fd = open(device, O_RDONLY)) == -1) {
++    goto error;
++  }
++#ifdef AUDIO_GETFORMAT
++  if (ioctl(fd, AUDIO_GETFORMAT, format) != 0) {
++    goto error;
++  }
++#endif
++#ifdef AUDIO_GETPROPS
++  if (ioctl(fd, AUDIO_GETPROPS, props) != 0) {
++    goto error;
++  }
++#endif
++  if (ioctl(fd, AUDIO_GETDEV, dev) != 0) {
++    goto error;
++  }
++  close(fd);
++  return CUBEB_OK;
++error:
++  if (fd != -1) {
++    close(fd);
++  }
++  return CUBEB_ERROR;
++}
+ 
+-    if (s->conv) {
+-      float_to_s16(s->buf, got * s->n_channles);
+-    }
++/*
++ * XXX: PR kern/54264
++ */
++static int
++sunaudio_prinfo_verify_sanity(struct audio_prinfo * prinfo)
++{
++   return prinfo->precision >= 8 && prinfo->precision <= 32 &&
++     prinfo->channels >= 1 && prinfo->channels < SUN_MAX_CHANNELS &&
++     prinfo->sample_rate < SUN_MAX_RATE && prinfo->sample_rate > SUN_MIN_RATE;
++}
++
++#ifndef CUBEB_OLD_API
++static int
++sunaudio_enumerate_devices(cubeb * context, cubeb_device_type type,
++                      cubeb_device_collection * collection)
++{
++  unsigned i;
++  cubeb_device_info device = {0};
++  char dev[16] = SUN_DEFAULT_DEVICE;
++  char dev_friendly[64];
++  struct audio_info hwfmt;
++  struct audio_device hwname;
++  struct audio_prinfo *prinfo = NULL;
++  int hwprops;
+ 
+-    unsigned int avail = got * 2 * s->n_channles; // coverted to s16
+-    unsigned int pos = 0;
++  collection->device = calloc(SUN_DEVICE_COUNT, sizeof(cubeb_device_info));
++  if (collection->device == NULL) {
++    return CUBEB_ERROR;
++  }
++  collection->count = 0;
+ 
+-    while (avail > 0 && s->active) {
+-      int written = write(s->fd, s->buf + pos, avail);
+-      if (written == -1) {
+-        if (errno != EINTR && errno != EWOULDBLOCK) {
+-          DPR("sunaudio_mainloop() write err\n");
+-          state = CUBEB_STATE_ERROR;
+-          break;
+-        }
+-        pthread_mutex_unlock(&s->mutex);
+-        struct timespec ts = {0, 10000}; // 10 ms
+-        nanosleep(&ts, NULL);
+-        pthread_mutex_lock(&s->mutex);
+-      } else {
+-        pos += written;
+-        DPR("sunaudio_mainloop() write %d pos %d\n", written, pos);
+-        s->frm_played += written / 2 / s->n_channles;
+-        avail -= written;
++  for (i = 0; i < SUN_DEVICE_COUNT; ++i) {
++    if (i > 0) {
++      (void)snprintf(dev, sizeof(dev), "/dev/audio%u", i - 1);
++    }
++    if (sunaudio_get_hwinfo(dev, &hwfmt, &hwprops, &hwname) != CUBEB_OK) {
++      continue;
++    }
++#ifdef AUDIO_GETPROPS
++    device.type = 0;
++    if ((hwprops & AUDIO_PROP_CAPTURE) != 0 &&
++        sunaudio_prinfo_verify_sanity(&hwfmt.record)) {
++      /* the device supports recording, probably */
++      device.type |= CUBEB_DEVICE_TYPE_INPUT;
++    }
++    if ((hwprops & AUDIO_PROP_PLAYBACK) != 0 &&
++        sunaudio_prinfo_verify_sanity(&hwfmt.play)) {
++      /* the device supports playback, probably */
++      device.type |= CUBEB_DEVICE_TYPE_OUTPUT;
++    }
++    switch (device.type) {
++    case 0:
++      /* device doesn't do input or output, aliens probably involved */
++      continue;
++    case CUBEB_DEVICE_TYPE_INPUT:
++      if ((type & CUBEB_DEVICE_TYPE_INPUT) == 0) {
++        /* this device is input only, not scanning for those, skip it */
++        continue;
+       }
+-    }
+-
+-    if ((got  < s->n_frm)) {
+-      DPR("sunaudio_mainloop() drained\n");
+-      state = CUBEB_STATE_DRAINED;
+       break;
++    case CUBEB_DEVICE_TYPE_OUTPUT:
++      if ((type & CUBEB_DEVICE_TYPE_OUTPUT) == 0) {
++        /* this device is output only, not scanning for those, skip it */
++        continue;
++      }
++      break;
++    }
++    if ((type & CUBEB_DEVICE_TYPE_INPUT) != 0) {
++      prinfo = &hwfmt.record;
+     }
++    if ((type & CUBEB_DEVICE_TYPE_OUTPUT) != 0) {
++      prinfo = &hwfmt.play;
++    }
++#endif
++    if (i > 0) {
++      (void)snprintf(dev_friendly, sizeof(dev_friendly), "%s %s %s (%d)",
++                     hwname.name, hwname.version, hwname.config, i - 1);
++    } else {
++      (void)snprintf(dev_friendly, sizeof(dev_friendly), "%s %s %s (default)",
++                     hwname.name, hwname.version, hwname.config);
++    }
++    device.devid = (void *)(uintptr_t)i;
++    device.device_id = strdup(dev);
++    device.friendly_name = strdup(dev_friendly);
++    device.group_id = strdup(dev);
++    device.vendor_name = strdup(hwname.name);
++    device.type = type;
++    device.state = CUBEB_DEVICE_STATE_ENABLED;
++    device.preferred = (i == 0) ? CUBEB_DEVICE_PREF_ALL : CUBEB_DEVICE_PREF_NONE;
++#ifdef AUDIO_GETFORMAT
++    device.max_channels = prinfo->channels;
++    device.default_rate = prinfo->sample_rate;
++#else
++    device.max_channels = 2;
++    device.default_rate = SUN_PREFER_RATE;
++#endif
++    device.default_format = CUBEB_DEVICE_FMT_S16NE;
++    device.format = CUBEB_DEVICE_FMT_S16NE;
++    device.min_rate = SUN_MIN_RATE;
++    device.max_rate = SUN_MAX_RATE;
++    device.latency_lo = SUN_LATENCY_MS * SUN_MIN_RATE / 1000;
++    device.latency_hi = SUN_LATENCY_MS * SUN_MAX_RATE / 1000;
++    collection->device[collection->count++] = device;
+   }
++  return CUBEB_OK;
++}
++#endif
+ 
+-  pthread_mutex_unlock(&s->mutex);
+-  s->state_cb(s, s->arg, state);
++#ifndef CUBEB_OLD_API
++static int
++sunaudio_device_collection_destroy(cubeb * context,
++                              cubeb_device_collection * collection)
++{
++  unsigned i;
+ 
+-  return NULL;
++  for (i = 0; i < collection->count; ++i) {
++    free((char *)collection->device[i].device_id);
++    free((char *)collection->device[i].friendly_name);
++    free((char *)collection->device[i].group_id);
++    free((char *)collection->device[i].vendor_name);
++  }
++  free(collection->device);
++  return CUBEB_OK;
+ }
++#endif
+ 
+-/*static*/ int
+-sunaudio_init(cubeb **context, char const *context_name)
++static int
++sunaudio_copy_params(int fd, cubeb_stream * stream, cubeb_stream_params * params,
++                struct audio_info * info, struct audio_prinfo * prinfo)
+ {
+-  DPR("sunaudio_init(%s)\n", context_name);
+-  *context = malloc(sizeof(*context));
+-  (*context)->ops = &sunaudio_ops;
+-  (void)context_name;
++  prinfo->channels = params->channels;
++  prinfo->sample_rate = params->rate;
++  prinfo->precision = 16;
++#ifdef AUDIO_ENCODING_SLINEAR_LE
++  switch (params->format) {
++  case CUBEB_SAMPLE_S16LE:
++    prinfo->encoding = AUDIO_ENCODING_SLINEAR_LE;
++    break;
++  case CUBEB_SAMPLE_S16BE:
++    prinfo->encoding = AUDIO_ENCODING_SLINEAR_BE;
++    break;
++  case CUBEB_SAMPLE_FLOAT32NE:
++    stream->floating = 1;
++    prinfo->encoding = AUDIO_ENCODING_SLINEAR;
++    break;
++  default:
++    return CUBEB_ERROR_INVALID_FORMAT;
++  }
++#else
++  switch (params->format) {
++  case CUBEB_SAMPLE_S16NE:
++    prinfo->encoding = AUDIO_ENCODING_LINEAR;
++    break;
++  case CUBEB_SAMPLE_FLOAT32NE:
++    stream->floating = 1;
++    prinfo->encoding = AUDIO_ENCODING_LINEAR;
++    break;
++  default:
++    return CUBEB_ERROR_INVALID_FORMAT;
++  }
++#endif
++  if (ioctl(fd, AUDIO_SETINFO, info) == -1) {
++    return CUBEB_ERROR;
++  }
++  if (ioctl(fd, AUDIO_GETINFO, info) == -1) {
++    return CUBEB_ERROR;
++  }
+   return CUBEB_OK;
+ }
+ 
+-static char const *
+-sunaudio_get_backend_id(cubeb *context)
++static int
++sunaudio_stream_stop(cubeb_stream * s)
+ {
+-  return "sunaudio";
++  pthread_mutex_lock(&s->mutex);
++  if (s->running) {
++    s->running = 0;
++    pthread_mutex_unlock(&s->mutex);
++    pthread_join(s->thread, NULL);
++  } else {
++    pthread_mutex_unlock(&s->mutex);
++  }
++  return CUBEB_OK;
+ }
+ 
+ static void
+-sunaudio_destroy(cubeb *context)
++sunaudio_stream_destroy(cubeb_stream * s)
+ {
+-  DPR("sunaudio_destroy()\n");
+-  free(context);
++  pthread_mutex_destroy(&s->mutex);
++  sunaudio_stream_stop(s);
++  if (s->play_fd != -1) {
++    close(s->play_fd);
++  }
++  if (s->record_fd != -1) {
++    close(s->record_fd);
++  }
++  free(s->f_play_buf);
++  free(s->f_record_buf);
++  free(s->play_buf);
++  free(s->record_buf);
++  free(s);
+ }
+ 
+-static int
+-sunaudio_stream_init(cubeb *context,
+-                  cubeb_stream **stream,
+-                  char const *stream_name,
+-                  cubeb_devid input_device,
+-                  cubeb_stream_params * input_stream_params,
+-                  cubeb_devid output_device,
+-                  cubeb_stream_params * output_stream_params,
+-                  unsigned int latency,
+-                  cubeb_data_callback data_callback,
+-                  cubeb_state_callback state_callback,
+-                  void *user_ptr)
+-{
+-  struct cubeb_stream *s;
+-  DPR("sunaudio_stream_init(%s)\n", stream_name);
+-  size_t size;
+-
+-  s = malloc(sizeof(struct cubeb_stream));
+-  if (s == NULL)
+-    return CUBEB_ERROR;
+-  s->context = context;
++static void
++sunaudio_float_to_linear(float * in, int16_t * out,
++                    unsigned channels, long frames, float vol)
++{
++  unsigned i, sample_count = frames * channels;
++  float multiplier = vol * 0x8000;
+ 
+-  // If UTAUDIODEV is set, use it with Sun Audio interface
+-  char * sa_device_name = getenv("UTAUDIODEV");
+-  char * dsp_device_name = NULL;
+-  if (!sa_device_name) {
+-    dsp_device_name = getenv("AUDIODSP");
+-    if (!dsp_device_name) {
+-      dsp_device_name = DEFAULT_DSP_DEVICE;
+-    }
+-    sa_device_name = getenv("AUDIODEV");
+-    if (!sa_device_name) {
+-      sa_device_name = DEFAULT_AUDIO_DEVICE;
++  for (i = 0; i < sample_count; ++i) {
++    int32_t sample = lrintf(in[i] * multiplier);
++    if (sample < -0x8000) {
++      out[i] = -0x8000;
++    } else if (sample > 0x7fff) {
++      out[i] = 0x7fff;
++    } else {
++      out[i] = sample;
+     }
+   }
++}
+ 
+-  s->using_oss = 0;
+-  // Try to use OSS if available
+-  if (dsp_device_name) {
+-    s->fd = open(dsp_device_name, O_WRONLY | O_NONBLOCK);
+-    if (s->fd >= 0) {
+-      s->using_oss = 1;
+-    }
+-  }
++static void
++sunaudio_linear_to_float(int16_t * in, float * out,
++                    unsigned channels, long frames)
++{
++  unsigned i, sample_count = frames * channels;
+ 
+-  // Try Sun Audio
+-  if (!s->using_oss) {
+-    s->fd = open(sa_device_name, O_WRONLY | O_NONBLOCK);
++  for (i = 0; i < sample_count; ++i) {
++    out[i] = (1.0 / 0x8000) * in[i];
+   }
++}
+ 
+-  if (s->fd < 0) {
+-    free(s);
+-    DPR("sunaudio_stream_init(), open() failed\n");
+-    return CUBEB_ERROR;
+-  }
++static void
++sunaudio_linear_set_vol(int16_t * buf, unsigned channels, long frames, float vol)
++{
++  unsigned i, sample_count = frames * channels;
++  int32_t multiplier = vol * 0x8000;
+ 
+-  if (s->using_oss) {
+-    if (ioctl(s->fd, SNDCTL_DSP_SPEED, &output_stream_params->rate) < 0) {
+-      DPR("ioctl SNDCTL_DSP_SPEED failed.\n");
+-      close(s->fd);
+-      free(s);
+-      return CUBEB_ERROR_INVALID_FORMAT;
+-    }
+-
+-    if (ioctl(s->fd, SNDCTL_DSP_CHANNELS, &output_stream_params->channels) < 0) {
+-      DPR("ioctl SNDCTL_DSP_CHANNELS failed.\n");
+-      close(s->fd);
+-      free(s);
+-      return CUBEB_ERROR_INVALID_FORMAT;
+-    }
+-
+-    int format = AFMT_S16_NE;
+-    if (ioctl(s->fd, SNDCTL_DSP_SETFMT, &format) < 0) {
+-      DPR("ioctl SNDCTL_DSP_SETFMT failed.\n");
+-      close(s->fd);
+-      free(s);
+-      return CUBEB_ERROR_INVALID_FORMAT;
+-    }
+-  } else {
+-    audio_info_t audio_info;
+-    AUDIO_INITINFO(&audio_info)
+-    audio_info.play.sample_rate = output_stream_params->rate;
+-    audio_info.play.channels = output_stream_params->channels;
+-    audio_info.play.encoding = AUDIO_ENCODING_LINEAR;
+-    audio_info.play.precision = 16;
+-    if (ioctl(s->fd, AUDIO_SETINFO, &audio_info) == -1) {
+-      DPR("ioctl AUDIO_SETINFO failed.\n");
+-      close(s->fd);
+-      free(s);
+-      return CUBEB_ERROR_INVALID_FORMAT;
+-    }
++  for (i = 0; i < sample_count; ++i) {
++    buf[i] = (buf[i] * multiplier) >> 15;
+   }
++}
+ 
+-  s->conv = 0;
+-  switch (output_stream_params->format) {
+-    case CUBEB_SAMPLE_S16NE:
+-      s->bytes_per_ch = 2;
++static void *
++sunaudio_io_routine(void * arg)
++{
++  cubeb_stream *s = arg;
++  cubeb_state state = CUBEB_STATE_STARTED;
++  size_t to_read = 0;
++  long to_write = 0;
++  size_t write_ofs = 0;
++  size_t read_ofs = 0;
++  int drain = 0;
++
++  s->state_cb(s, s->user_ptr, CUBEB_STATE_STARTED);
++  while (state != CUBEB_STATE_ERROR) {
++    pthread_mutex_lock(&s->mutex);
++    if (!s->running) {
++      pthread_mutex_unlock(&s->mutex);
++      state = CUBEB_STATE_STOPPED;
+       break;
+-    case CUBEB_SAMPLE_FLOAT32NE:
+-      s->bytes_per_ch = 4;
+-      s->conv = 1;
++    }
++    pthread_mutex_unlock(&s->mutex);
++    if (s->floating) {
++      if (s->record_fd != -1) {
++        sunaudio_linear_to_float(s->record_buf, s->f_record_buf,
++                            s->r_info.record.channels, SUN_BUFFER_FRAMES);
++      }
++      to_write = s->data_cb(s, s->user_ptr,
++                            s->f_record_buf, s->f_play_buf, SUN_BUFFER_FRAMES);
++      if (to_write == CUBEB_ERROR) {
++        state = CUBEB_STATE_ERROR;
++        break;
++      }
++      if (s->play_fd != -1) {
++        pthread_mutex_lock(&s->mutex);
++        sunaudio_float_to_linear(s->f_play_buf, s->play_buf,
++                            s->p_info.play.channels, to_write, s->volume);
++        pthread_mutex_unlock(&s->mutex);
++      }
++    } else {
++      to_write = s->data_cb(s, s->user_ptr,
++                            s->record_buf, s->play_buf, SUN_BUFFER_FRAMES);
++      if (to_write == CUBEB_ERROR) {
++        state = CUBEB_STATE_ERROR;
++        break;
++      }
++      if (s->play_fd != -1) {
++        pthread_mutex_lock(&s->mutex);
++        sunaudio_linear_set_vol(s->play_buf, s->p_info.play.channels, to_write, s->volume);
++        pthread_mutex_unlock(&s->mutex);
++      }
++    }
++    if (to_write < SUN_BUFFER_FRAMES) {
++      drain = 1;
++    }
++    to_write = s->play_fd != -1 ? to_write : 0;
++    to_read = s->record_fd != -1 ? SUN_BUFFER_FRAMES : 0;
++    write_ofs = 0;
++    read_ofs = 0;
++    while (to_write > 0 || to_read > 0) {
++      size_t bytes;
++      ssize_t n, frames;
++
++      if (to_write > 0) {
++        bytes = FRAMES_TO_BYTES(to_write, s->p_info.play.channels);
++        if ((n = write(s->play_fd, s->play_buf + write_ofs, bytes)) < 0) {
++          state = CUBEB_STATE_ERROR;
++          break;
++        }
++        frames = BYTES_TO_FRAMES(n, s->p_info.play.channels);
++        pthread_mutex_lock(&s->mutex);
++        s->frames_written += frames;
++        pthread_mutex_unlock(&s->mutex);
++        to_write -= frames;
++        write_ofs += frames;
++      }
++      if (to_read > 0) {
++        bytes = FRAMES_TO_BYTES(to_read, s->r_info.record.channels);
++        if ((n = read(s->record_fd, s->record_buf + read_ofs, bytes)) < 0) {
++          state = CUBEB_STATE_ERROR;
++          break;
++        }
++        frames = BYTES_TO_FRAMES(n, s->r_info.record.channels);
++        to_read -= frames;
++        read_ofs += frames;
++      }
++    }
++    if (drain && state != CUBEB_STATE_ERROR) {
++      state = CUBEB_STATE_DRAINED;
+       break;
+-    default:
+-      DPR("sunaudio_stream_init() unsupported format\n");
+-      close(s->fd);
+-      free(s);
+-      return CUBEB_ERROR_INVALID_FORMAT;
++    }
+   }
++  s->state_cb(s, s->user_ptr, state);
++  return NULL;
++}
+ 
+-  s->active = 0;
+-  s->rate = output_stream_params->rate;
+-  s->n_channles = output_stream_params->channels;
+-  s->data_cb = data_callback;
++static int
++sunaudio_stream_init(cubeb * context,
++                cubeb_stream ** stream,
++                char const * stream_name,
++                cubeb_devid input_device,
++                cubeb_stream_params * input_stream_params,
++                cubeb_devid output_device,
++                cubeb_stream_params * output_stream_params,
++                unsigned latency_frames,
++                cubeb_data_callback data_callback,
++                cubeb_state_callback state_callback,
++                void * user_ptr)
++{
++  int ret = CUBEB_OK;
++  cubeb_stream *s = NULL;
++
++  (void)stream_name;
++  (void)latency_frames;
++  if ((s = calloc(1, sizeof(cubeb_stream))) == NULL) {
++    ret = CUBEB_ERROR;
++    goto error;
++  }
++  s->record_fd = -1;
++  s->play_fd = -1;
++  if (input_device != 0) {
++    snprintf(s->input_name, sizeof(s->input_name),
++      "/dev/audio%zu", (uintptr_t)input_device - 1);
++  } else {
++    snprintf(s->input_name, sizeof(s->input_name), "%s", SUN_DEFAULT_DEVICE);
++  }
++  if (output_device != 0) {
++    snprintf(s->output_name, sizeof(s->output_name),
++      "/dev/audio%zu", (uintptr_t)output_device - 1);
++  } else {
++    snprintf(s->output_name, sizeof(s->output_name), "%s", SUN_DEFAULT_DEVICE);
++  }
++  if (input_stream_params != NULL) {
++#ifndef CUBEB_OLD_API
++    if (input_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK) {
++      ret = CUBEB_ERROR_NOT_SUPPORTED;
++      goto error;
++    }
++#endif
++    if (s->record_fd == -1) {
++      if ((s->record_fd = open(s->input_name, O_RDONLY)) == -1) {
++        ret = CUBEB_ERROR_DEVICE_UNAVAILABLE;
++        goto error;
++      }
++    }
++    AUDIO_INITINFO(&s->r_info);
++#ifdef AUMODE_RECORD
++    s->r_info.mode = AUMODE_RECORD;
++#endif
++    if ((ret = sunaudio_copy_params(s->record_fd, s, input_stream_params,
++                               &s->r_info, &s->r_info.record)) != CUBEB_OK) {
++      goto error;
++    }
++  }
++  if (output_stream_params != NULL) {
++#ifndef CUBEB_OLD_API
++    if (output_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK) {
++      ret = CUBEB_ERROR_NOT_SUPPORTED;
++      goto error;
++    }
++#endif
++    if (s->play_fd == -1) {
++      if ((s->play_fd = open(s->output_name, O_WRONLY)) == -1) {
++        ret = CUBEB_ERROR_DEVICE_UNAVAILABLE;
++        goto error;
++      }
++    }
++    AUDIO_INITINFO(&s->p_info);
++#ifdef AUMODE_PLAY
++    s->p_info.mode = AUMODE_PLAY;
++#endif
++    if ((ret = sunaudio_copy_params(s->play_fd, s, output_stream_params,
++                               &s->p_info, &s->p_info.play)) != CUBEB_OK) {
++      goto error;
++    }
++  }
++  s->context = context;
++  s->volume = 1.0;
+   s->state_cb = state_callback;
+-  s->arg = user_ptr;
++  s->data_cb = data_callback;
++  s->user_ptr = user_ptr;
+   if (pthread_mutex_init(&s->mutex, NULL) != 0) {
+-    free(s);
+-    return CUBEB_ERROR;
++    goto error;
+   }
+-  s->frm_played = 0;
+-  s->n_frm = s->rate * BUF_SIZE_MS / 1000;
+-  s->buffer_size = s->bytes_per_ch * s->n_channles * s->n_frm;
+-  s->buf = malloc(s->buffer_size);
+-  if (s->buf == NULL) {
+-    close(s->fd);
+-    free(s);
+-    return CUBEB_ERROR;
++  if (s->play_fd != -1 && (s->play_buf = calloc(SUN_BUFFER_FRAMES,
++      s->p_info.play.channels * sizeof(int16_t))) == NULL) {
++    ret = CUBEB_ERROR;
++    goto error;
++  }
++  if (s->record_fd != -1 && (s->record_buf = calloc(SUN_BUFFER_FRAMES,
++      s->r_info.record.channels * sizeof(int16_t))) == NULL) {
++    ret = CUBEB_ERROR;
++    goto error;
++  }
++  if (s->floating) {
++    if (s->play_fd != -1 && (s->f_play_buf = calloc(SUN_BUFFER_FRAMES,
++        s->p_info.play.channels * sizeof(float))) == NULL) {
++      ret = CUBEB_ERROR;
++      goto error;
++    }
++    if (s->record_fd != -1 && (s->f_record_buf = calloc(SUN_BUFFER_FRAMES,
++        s->r_info.record.channels * sizeof(float))) == NULL) {
++      ret = CUBEB_ERROR;
++      goto error;
++    }
+   }
+-
+   *stream = s;
+-  DPR("sunaudio_stream_init() end, ok\n");
+   return CUBEB_OK;
+-}
+-
+-static void
+-sunaudio_stream_destroy(cubeb_stream *s)
+-{
+-  DPR("sunaudio_stream_destroy()\n");
+-  if (s->fd > 0) {
+-    // Flush buffer
+-    if (s->using_oss) {
+-      ioctl(s->fd, SNDCTL_DSP_HALT_OUTPUT);
+-    } else {
+-      ioctl(s->fd, I_FLUSH);
+-    }
+-    close(s->fd);
++error:
++  if (s != NULL) {
++    sunaudio_stream_destroy(s);
+   }
+-  free(s->buf);
+-  free(s);
++  return ret;
+ }
+ 
+ static int
+-sunaudio_stream_start(cubeb_stream *s)
++sunaudio_stream_start(cubeb_stream * s)
+ {
+-  int err;
+-
+-  DPR("sunaudio_stream_start()\n");
+-  s->active = 1;
+-  err = pthread_create(&s->th, NULL, sunaudio_mainloop, s);
+-  if (err) {
+-    s->active = 0;
++  s->running = 1;
++  if (pthread_create(&s->thread, NULL, sunaudio_io_routine, s) != 0) {
+     return CUBEB_ERROR;
+   }
+   return CUBEB_OK;
+ }
+ 
+ static int
+-sunaudio_stream_stop(cubeb_stream *s)
++sunaudio_stream_get_position(cubeb_stream * s, uint64_t * position)
+ {
+-  void *dummy;
++#ifdef AUDIO_GETOOFFS
++  struct audio_offset offset;
+ 
+-  DPR("sunaudio_stream_stop()\n");
+-  if (s->active) {
+-    s->active = 0;
+-    pthread_join(s->th, &dummy);
++  if (ioctl(s->play_fd, AUDIO_GETOOFFS, &offset) == -1) {
++    return CUBEB_ERROR;
+   }
++  s->blocks_written += offset.deltablks;
++  *position = BYTES_TO_FRAMES(s->blocks_written * s->p_info.blocksize,
++                              s->p_info.play.channels);
+   return CUBEB_OK;
+-}
+-
+-static int
+-sunaudio_stream_get_position(cubeb_stream *s, uint64_t *p)
+-{
+-  int rv = CUBEB_OK;
++#else
+   pthread_mutex_lock(&s->mutex);
+-  if (s->active && s->fd > 0) {
+-    if (s->using_oss) {
+-      int delay;
+-      ioctl(s->fd, SNDCTL_DSP_GETODELAY, &delay);
+-      int64_t t = s->frm_played - delay / s->n_channles / 2;
+-      if (t < 0) {
+-        *p = 0;
+-      } else {
+-        *p = t;
+-      }
+-    } else {
+-      audio_info_t info;
+-      ioctl(s->fd, AUDIO_GETINFO, &info);
+-      *p = info.play.samples;
+-    }
+-    DPR("sunaudio_stream_get_position() %lld\n", *p);
+-  } else {
+-    rv = CUBEB_ERROR;
+-  }
++  *position = s->frames_written;
+   pthread_mutex_unlock(&s->mutex);
+-  return rv;
++  return CUBEB_OK;
++#endif
+ }
+ 
+ static int
+-sunaudio_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
++sunaudio_stream_get_latency(cubeb_stream * stream, uint32_t * latency)
+ {
+-  if (!ctx || !max_channels)
+-    return CUBEB_ERROR;
++#ifdef AUDIO_GETBUFINFO
++  struct audio_info info;
+ 
+-  *max_channels = 2;
++  if (ioctl(stream->play_fd, AUDIO_GETBUFINFO, &info) == -1) {
++    return CUBEB_ERROR;
++  }
+ 
++  *latency = BYTES_TO_FRAMES(info.play.seek + info.blocksize,
++                             info.play.channels);
+   return CUBEB_OK;
++#else
++  cubeb_stream_params params;
++
++  params.rate = stream->p_info.play.sample_rate;
++
++  return sunaudio_get_min_latency(NULL, params, latency);
++#endif
+ }
+ 
+ static int
+-sunaudio_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
++sunaudio_stream_set_volume(cubeb_stream * stream, float volume)
+ {
+-  if (!ctx || !rate)
+-    return CUBEB_ERROR;
+-
+-  // XXX Not yet implemented.
+-  *rate = 44100;
+-
++  pthread_mutex_lock(&stream->mutex);
++  stream->volume = volume;
++  pthread_mutex_unlock(&stream->mutex);
+   return CUBEB_OK;
+ }
+ 
+ static int
+-sunaudio_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_ms)
++sunaudio_get_current_device(cubeb_stream * stream, cubeb_device ** const device)
+ {
+-  if (!ctx || !latency_ms)
++  *device = calloc(1, sizeof(cubeb_device));
++  if (*device == NULL) {
+     return CUBEB_ERROR;
+-
+-  // XXX Not yet implemented.
+-  *latency_ms = 20;
+-
++  }
++  (*device)->input_name = stream->record_fd != -1 ?
++    strdup(stream->input_name) : NULL;
++  (*device)->output_name = stream->play_fd != -1 ?
++    strdup(stream->output_name) : NULL;
+   return CUBEB_OK;
+ }
+ 
+ static int
+-sunaudio_stream_get_latency(cubeb_stream * s, uint32_t * latency)
++sunaudio_stream_device_destroy(cubeb_stream * stream, cubeb_device * device)
+ {
+-  if (!s || !latency)
+-    return CUBEB_ERROR;
+-
+-  int rv = CUBEB_OK;
+-  pthread_mutex_lock(&s->mutex);
+-  if (s->active && s->fd > 0) {
+-    if (s->using_oss) {
+-      int delay;
+-      ioctl(s->fd, SNDCTL_DSP_GETODELAY, &delay);
+-      *latency = delay / s->n_channles / 2 / s->rate;
+-    } else {
+-      audio_info_t info;
+-      ioctl(s->fd, AUDIO_GETINFO, &info);
+-      *latency = (s->frm_played - info.play.samples) / s->rate;
+-    }
+-    DPR("sunaudio_stream_get_position() %lld\n", *p);
+-  } else {
+-    rv = CUBEB_ERROR;
+-  }
+-  pthread_mutex_unlock(&s->mutex);
+-  return rv;
++  (void)stream;
++  free(device->input_name);
++  free(device->output_name);
++  free(device);
++  return CUBEB_OK;
+ }
+ 
+ static struct cubeb_ops const sunaudio_ops = {
+   .init = sunaudio_init,
+   .get_backend_id = sunaudio_get_backend_id,
+-  .destroy = sunaudio_destroy,
++  .get_max_channel_count = sunaudio_get_max_channel_count,
++  .get_min_latency = sunaudio_get_min_latency,
+   .get_preferred_sample_rate = sunaudio_get_preferred_sample_rate,
++#ifndef CUBEB_OLD_API
++  .enumerate_devices = sunaudio_enumerate_devices,
++  .device_collection_destroy = sunaudio_device_collection_destroy,
++#endif
++  .destroy = sunaudio_destroy,
+   .stream_init = sunaudio_stream_init,
+   .stream_destroy = sunaudio_stream_destroy,
+   .stream_start = sunaudio_stream_start,
+   .stream_stop = sunaudio_stream_stop,
++#ifndef CUBEB_OLD_API
++  .stream_reset_default_device = NULL,
++#endif
+   .stream_get_position = sunaudio_stream_get_position,
+-  .get_max_channel_count = sunaudio_get_max_channel_count,
+-  .get_min_latency = sunaudio_get_min_latency,
+-  .stream_get_latency = sunaudio_stream_get_latency
++  .stream_get_latency = sunaudio_stream_get_latency,
++  .stream_set_volume = sunaudio_stream_set_volume,
++  .stream_set_panning = NULL,
++  .stream_get_current_device = sunaudio_get_current_device,
++  .stream_device_destroy = sunaudio_stream_device_destroy,
++  .stream_register_device_changed_callback = NULL,
++  .register_device_collection_changed = NULL
+ };
Index: pkgsrc/www/basilisk/patches/patch-platform_media_libtheora_moz.build
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_media_libtheora_moz.build:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_media_libtheora_moz.build        Fri Apr 25 21:25:03 2025
@@ -0,0 +1,16 @@
+$NetBSD: patch-platform_media_libtheora_moz.build,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Runtime CPU detection on ARM is currently unimplemented for anything
+except Linux.
+
+--- platform/media/libtheora/moz.build.orig    2024-07-29 10:59:14.581061883 +0000
++++ platform/media/libtheora/moz.build
+@@ -82,7 +82,7 @@ if CONFIG['INTEL_ARCHITECTURE']:
+             'lib/x86/x86state.c',
+         ]
+ 
+-if CONFIG['GNU_AS']:
++if CONFIG['GNU_AS'] and CONFIG['OS_ARCH'] == 'Linux':
+     if CONFIG['CPU_ARCH'] == 'arm':
+         SOURCES += [
+             'lib/arm/armcpu.c',
Index: pkgsrc/www/basilisk/patches/patch-platform_media_libvpx_config_linux_arm_vpx__config.h
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_media_libvpx_config_linux_arm_vpx__config.h:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_media_libvpx_config_linux_arm_vpx__config.h      Fri Apr 25 21:25:03 2025
@@ -0,0 +1,19 @@
+$NetBSD: patch-platform_media_libvpx_config_linux_arm_vpx__config.h,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Runtime CPU detection on ARM is currently unimplemented for anything
+except Linux.
+
+--- platform/media/libvpx/config/linux/arm/vpx_config.h.orig   2024-07-29 10:28:36.006671626 +0000
++++ platform/media/libvpx/config/linux/arm/vpx_config.h
+@@ -48,7 +48,11 @@
+ #define CONFIG_DEBUG_LIBS 0
+ #define CONFIG_DEQUANT_TOKENS 0
+ #define CONFIG_DC_RECON 0
++#ifdef __linux
+ #define CONFIG_RUNTIME_CPU_DETECT 1
++#else
++#define CONFIG_RUNTIME_CPU_DETECT 0
++#endif
+ #define CONFIG_POSTPROC 0
+ #define CONFIG_VP9_POSTPROC 0
+ #define CONFIG_MULTITHREAD 1
Index: pkgsrc/www/basilisk/patches/patch-platform_media_webrtc_trunk_webrtc_modules_audio__device_audio__device.gypi
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_media_webrtc_trunk_webrtc_modules_audio__device_audio__device.gypi:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_media_webrtc_trunk_webrtc_modules_audio__device_audio__device.gypi       Fri Apr 25 21:25:03 2025
@@ -0,0 +1,15 @@
+$NetBSD: patch-platform_media_webrtc_trunk_webrtc_modules_audio__device_audio__device.gypi,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Add support for non-linux unixes.
+
+--- platform/media/webrtc/trunk/webrtc/modules/audio_device/audio_device.gypi.orig     2025-04-24 10:36:58.372649812 +0000
++++ platform/media/webrtc/trunk/webrtc/modules/audio_device/audio_device.gypi
+@@ -66,7 +66,7 @@
+             'sndio',
+           ],
+         }], # include_sndio_audio==1
+-        ['OS=="linux" or include_alsa_audio==1 or include_pulse_audio==1', {
++        ['OS=="linux" or OS=="solaris" or os_bsd==1 or include_alsa_audio==1 or include_pulse_audio==1', {
+           'include_dirs': [
+             'linux',
+           ],
Index: pkgsrc/www/basilisk/patches/patch-platform_netwerk_srtp_src_crypto_hash_hmac.c
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_netwerk_srtp_src_crypto_hash_hmac.c:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_netwerk_srtp_src_crypto_hash_hmac.c      Fri Apr 25 21:25:03 2025
@@ -0,0 +1,58 @@
+$NetBSD: patch-platform_netwerk_srtp_src_crypto_hash_hmac.c,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+NetBSD has a libc symbol called hmac.
+
+--- platform/netwerk/srtp/src/crypto/hash/hmac.c.orig  2025-04-24 11:13:21.485046106 +0000
++++ platform/netwerk/srtp/src/crypto/hash/hmac.c
+@@ -55,7 +55,7 @@ debug_module_t mod_hmac = {
+ 
+ err_status_t
+ hmac_alloc(auth_t **a, int key_len, int out_len) {
+-  extern auth_type_t hmac;
++  extern auth_type_t my_hmac;
+   uint8_t *pointer;
+ 
+   debug_print(mod_hmac, "allocating auth func with key length %d", key_len);
+@@ -79,21 +79,21 @@ hmac_alloc(auth_t **a, int key_len, int 
+ 
+   /* set pointers */
+   *a = (auth_t *)pointer;
+-  (*a)->type = &hmac;
++  (*a)->type = &my_hmac;
+   (*a)->state = pointer + sizeof(auth_t);  
+   (*a)->out_len = out_len;
+   (*a)->key_len = key_len;
+   (*a)->prefix_len = 0;
+ 
+   /* increment global count of all hmac uses */
+-  hmac.ref_count++;
++  my_hmac.ref_count++;
+ 
+   return err_status_ok;
+ }
+ 
+ err_status_t
+ hmac_dealloc(auth_t *a) {
+-  extern auth_type_t hmac;
++  extern auth_type_t my_hmac;
+   
+   /* zeroize entire state*/
+   octet_string_set_to_zero((uint8_t *)a, 
+@@ -103,7 +103,7 @@ hmac_dealloc(auth_t *a) {
+   crypto_free(a);
+   
+   /* decrement global count of all hmac uses */
+-  hmac.ref_count--;
++  my_hmac.ref_count--;
+ 
+   return err_status_ok;
+ }
+@@ -252,7 +252,7 @@ char hmac_description[] = "hmac sha-1 au
+  */
+ 
+ auth_type_t
+-hmac  = {
++my_hmac  = {
+   (auth_alloc_func)      hmac_alloc,
+   (auth_dealloc_func)    hmac_dealloc,
+   (auth_init_func)       hmac_init,
Index: pkgsrc/www/basilisk/patches/patch-platform_netwerk_srtp_src_crypto_kernel_crypto__kernel.c
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_netwerk_srtp_src_crypto_kernel_crypto__kernel.c:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_netwerk_srtp_src_crypto_kernel_crypto__kernel.c  Fri Apr 25 21:25:03 2025
@@ -0,0 +1,24 @@
+$NetBSD: patch-platform_netwerk_srtp_src_crypto_kernel_crypto__kernel.c,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+NetBSD has a libc symbol called hmac.
+
+--- platform/netwerk/srtp/src/crypto/kernel/crypto_kernel.c.orig       2025-04-24 11:18:08.323474546 +0000
++++ platform/netwerk/srtp/src/crypto/kernel/crypto_kernel.c
+@@ -77,7 +77,7 @@ extern cipher_type_t aes_cbc;
+  */
+ 
+ extern auth_type_t null_auth;
+-extern auth_type_t hmac;
++extern auth_type_t my_hmac;
+ 
+ /* crypto_kernel is a global variable, the only one of its datatype */
+ 
+@@ -162,7 +162,7 @@ crypto_kernel_init() {
+   status = crypto_kernel_load_auth_type(&null_auth, NULL_AUTH);
+   if (status)
+     return status;
+-  status = crypto_kernel_load_auth_type(&hmac, HMAC_SHA1);
++  status = crypto_kernel_load_auth_type(&my_hmac, HMAC_SHA1);
+   if (status)
+     return status;
+ 
Index: pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_md__netbsd.cfg
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_md__netbsd.cfg:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_md__netbsd.cfg        Fri Apr 25 21:25:03 2025
@@ -0,0 +1,65 @@
+$NetBSD: patch-platform_nsprpub_pr_include_md__netbsd.cfg,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Add NetBSD/arm64 support.
+
+--- platform/nsprpub/pr/include/md/_netbsd.cfg.orig    2024-07-10 01:54:53.000000000 -0700
++++ platform/nsprpub/pr/include/md/_netbsd.cfg 2024-08-05 12:51:14.262409653 -0700
+@@ -296,6 +296,58 @@
+ #define PR_BYTES_PER_WORD_LOG2   2
+ #define PR_BYTES_PER_DWORD_LOG2  3
+ 
++#elif defined(__aarch64__)
++
++#ifdef __ARM_BIG_ENDIAN
++#define IS_BIG_ENDIAN    1
++#undef  IS_LITTLE_ENDIAN
++#else
++#undef  IS_BIG_ENDIAN
++#define IS_LITTLE_ENDIAN 1
++#endif
++
++#define IS_64
++
++#define PR_BYTES_PER_BYTE   1
++#define PR_BYTES_PER_SHORT  2
++#define PR_BYTES_PER_INT    4
++#define PR_BYTES_PER_INT64  8
++#define PR_BYTES_PER_LONG   8
++#define PR_BYTES_PER_FLOAT  4
++#define PR_BYTES_PER_DOUBLE 8
++#define PR_BYTES_PER_WORD   8
++#define PR_BYTES_PER_DWORD  8
++
++#define PR_BITS_PER_BYTE    8
++#define PR_BITS_PER_SHORT   16
++#define PR_BITS_PER_INT     32
++#define PR_BITS_PER_INT64   64
++#define PR_BITS_PER_LONG    64
++#define PR_BITS_PER_FLOAT   32
++#define PR_BITS_PER_DOUBLE  64
++#define PR_BITS_PER_WORD    64
++
++#define PR_BITS_PER_BYTE_LOG2   3
++#define PR_BITS_PER_SHORT_LOG2  4
++#define PR_BITS_PER_INT_LOG2    5
++#define PR_BITS_PER_INT64_LOG2  6
++#define PR_BITS_PER_LONG_LOG2   6
++#define PR_BITS_PER_FLOAT_LOG2  5
++#define PR_BITS_PER_DOUBLE_LOG2 6
++#define PR_BITS_PER_WORD_LOG2   6
++
++#define PR_ALIGN_OF_SHORT   2
++#define PR_ALIGN_OF_INT     4
++#define PR_ALIGN_OF_LONG    8
++#define PR_ALIGN_OF_INT64   8
++#define PR_ALIGN_OF_FLOAT   4
++#define PR_ALIGN_OF_DOUBLE  8
++#define PR_ALIGN_OF_POINTER 8
++#define PR_ALIGN_OF_WORD    8
++
++#define PR_BYTES_PER_WORD_LOG2  3
++#define PR_BYTES_PER_DWORD_LOG2 3
++
+ #else
+ 
+ #error Must define constants for type sizes here.
Index: pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_md__netbsd.h
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_md__netbsd.h:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_md__netbsd.h  Fri Apr 25 21:25:03 2025
@@ -0,0 +1,15 @@
+$NetBSD: patch-platform_nsprpub_pr_include_md__netbsd.h,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Add NetBSD/arm64 support.
+
+--- platform/nsprpub/pr/include/md/_netbsd.h.orig      2024-07-10 01:54:53.000000000 -0700
++++ platform/nsprpub/pr/include/md/_netbsd.h   2024-08-05 12:48:09.663633172 -0700
+@@ -27,6 +27,8 @@
+ #define _PR_SI_ARCHITECTURE "sparc"
+ #elif defined(__mips__)
+ #define _PR_SI_ARCHITECTURE "mips"
++#elif defined(__aarch64__)
++#define _PR_SI_ARCHITECTURE "aarch64"
+ #elif defined(__arm32__) || defined(__arm__) || defined(__armel__) \
+     || defined(__armeb__)
+ #define _PR_SI_ARCHITECTURE "arm"
Index: pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_private_pprthred.h
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_private_pprthred.h:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_include_private_pprthred.h    Fri Apr 25 21:25:03 2025
@@ -0,0 +1,25 @@
+$NetBSD: patch-platform_nsprpub_pr_include_private_pprthred.h,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+pthread_t may be 64-bit, avoid integer truncation. 
+https://bugzilla.mozilla.org/show_bug.cgi?id=1718835
+
+--- platform/nsprpub/pr/include/private/pprthred.h.orig        2024-09-05 08:13:09.000000000 +0000
++++ platform/nsprpub/pr/include/private/pprthred.h
+@@ -19,6 +19,8 @@
+ #include <os2.h>
+ #endif
+ 
++#include <pthread.h>
++
+ PR_BEGIN_EXTERN_C
+ 
+ /*---------------------------------------------------------------------------
+@@ -59,7 +61,7 @@ NSPR_API(void) PR_DetachThread(void);
+ ** Get the id of the named thread. Each thread is assigned a unique id
+ ** when it is created or attached.
+ */
+-NSPR_API(PRUint32) PR_GetThreadID(PRThread *thread);
++NSPR_API(pthread_t) PR_GetThreadID(PRThread *thread);
+ 
+ /*
+ ** Set the procedure that is called when a thread is dumped. The procedure
Index: pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_src_pthreads_ptsynch.c
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_src_pthreads_ptsynch.c:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_src_pthreads_ptsynch.c        Fri Apr 25 21:25:03 2025
@@ -0,0 +1,110 @@
+$NetBSD: patch-platform_nsprpub_pr_src_pthreads_ptsynch.c,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+* Do not use pthread_equal() for non-valid thread pointers.
+  From kamin@ on source-changes-d%NetBSD.org@localhost.
+  https://mail-index.netbsd.org/source-changes-d/2020/02/03/msg012143.html
+
+https://bugzilla.mozilla.org/show_bug.cgi?id=1718838
+
+--- platform/nsprpub/pr/src/pthreads/ptsynch.c.orig    2024-09-05 08:13:09.000000000 +0000
++++ platform/nsprpub/pr/src/pthreads/ptsynch.c
+@@ -25,6 +25,13 @@ static pthread_condattr_t _pt_cvar_attr;
+ extern PTDebug pt_debug;  /* this is shared between several modules */
+ #endif  /* defined(DEBUG) */
+ 
++/* XXX, pthread_equal() is misused to compare non-valid thread pointers */
++static int
++pt_pthread_equal(pthread_t t1, pthread_t t2)
++{
++      return t1 == t2;
++}
++
+ #if defined(FREEBSD)
+ /*
+  * On older versions of FreeBSD, pthread_mutex_trylock returns EDEADLK.
+@@ -197,9 +204,9 @@ PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock 
+     PR_ASSERT(lock != NULL);
+     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(lock->mutex));
+     PR_ASSERT(PR_TRUE == lock->locked);
+-    PR_ASSERT(pthread_equal(lock->owner, self));
++    PR_ASSERT(pt_pthread_equal(lock->owner, self));
+ 
+-    if (!lock->locked || !pthread_equal(lock->owner, self)) {
++    if (!lock->locked || !pt_pthread_equal(lock->owner, self)) {
+         return PR_FAILURE;
+     }
+ 
+@@ -225,7 +232,7 @@ PR_IMPLEMENT(void) PR_AssertCurrentThrea
+      * to the correctness of PR_AssertCurrentThreadOwnsLock(), but
+      * this particular order makes the assertion more likely to
+      * catch errors. */
+-    PR_ASSERT(lock->locked && pthread_equal(lock->owner, pthread_self()));
++    PR_ASSERT(lock->locked && pt_pthread_equal(lock->owner, pthread_self()));
+ }
+ 
+ /**************************************************************/
+@@ -281,7 +288,7 @@ static void pt_PostNotifyToCvar(PRCondVa
+     _PT_Notified *notified = &cvar->lock->notified;
+ 
+     PR_ASSERT(PR_TRUE == cvar->lock->locked);
+-    PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
++    PR_ASSERT(pt_pthread_equal(cvar->lock->owner, pthread_self()));
+     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
+ 
+     while (1)
+@@ -369,7 +376,7 @@ PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PR
+     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
+     PR_ASSERT(PR_TRUE == cvar->lock->locked);
+     /* and it better be by us */
+-    PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
++    PR_ASSERT(pt_pthread_equal(cvar->lock->owner, pthread_self()));
+ 
+     if (_PT_THREAD_INTERRUPTED(thred)) {
+         goto aborted;
+@@ -582,7 +589,7 @@ PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryC
+ 
+     rv = pthread_mutex_lock(&mon->lock);
+     PR_ASSERT(0 == rv);
+-    if (pthread_equal(mon->owner, self)) {
++    if (pt_pthread_equal(mon->owner, self)) {
+         count = mon->entryCount;
+     }
+     rv = pthread_mutex_unlock(&mon->lock);
+@@ -598,7 +605,7 @@ PR_IMPLEMENT(void) PR_AssertCurrentThrea
+     rv = pthread_mutex_lock(&mon->lock);
+     PR_ASSERT(0 == rv);
+     PR_ASSERT(mon->entryCount != 0 &&
+-              pthread_equal(mon->owner, pthread_self()));
++              pt_pthread_equal(mon->owner, pthread_self()));
+     rv = pthread_mutex_unlock(&mon->lock);
+     PR_ASSERT(0 == rv);
+ #endif
+@@ -614,7 +621,7 @@ PR_IMPLEMENT(void) PR_EnterMonitor(PRMon
+     PR_ASSERT(0 == rv);
+     if (mon->entryCount != 0)
+     {
+-        if (pthread_equal(mon->owner, self)) {
++        if (pt_pthread_equal(mon->owner, self)) {
+             goto done;
+         }
+         while (mon->entryCount != 0)
+@@ -646,8 +653,8 @@ PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PR
+     PR_ASSERT(0 == rv);
+     /* the entries should be > 0 and we'd better be the owner */
+     PR_ASSERT(mon->entryCount > 0);
+-    PR_ASSERT(pthread_equal(mon->owner, self));
+-    if (mon->entryCount == 0 || !pthread_equal(mon->owner, self))
++    PR_ASSERT(pt_pthread_equal(mon->owner, self));
++    if (mon->entryCount == 0 || !pt_pthread_equal(mon->owner, self))
+     {
+         rv = pthread_mutex_unlock(&mon->lock);
+         PR_ASSERT(0 == rv);
+@@ -695,7 +702,7 @@ PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor
+     /* the entries better be positive */
+     PR_ASSERT(mon->entryCount > 0);
+     /* and it better be owned by us */
+-    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
++    PR_ASSERT(pt_pthread_equal(mon->owner, pthread_self()));
+ 
+     /* tuck these away 'till later */
+     saved_entries = mon->entryCount;
Index: pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_src_pthreads_ptthread.c
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_src_pthreads_ptthread.c:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_nsprpub_pr_src_pthreads_ptthread.c       Fri Apr 25 21:25:03 2025
@@ -0,0 +1,19 @@
+$NetBSD: patch-platform_nsprpub_pr_src_pthreads_ptthread.c,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+pthread_t may be 64-bit, avoid integer truncation.
+https://bugzilla.mozilla.org/show_bug.cgi?id=1718835
+
+--- platform/nsprpub/pr/src/pthreads/ptthread.c.orig   2024-09-05 08:13:09.000000000 +0000
++++ platform/nsprpub/pr/src/pthreads/ptthread.c
+@@ -1183,9 +1183,9 @@ PR_IMPLEMENT(void) PR_ProcessExit(PRIntn
+     _exit(status);
+ }
+ 
+-PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thred)
++PR_IMPLEMENT(pthread_t) PR_GetThreadID(PRThread *thred)
+ {
+-    return (PRUint32)thred->id;  /* and I don't know what they will do with it */
++    return (pthread_t)thred->id;  /* and I don't know what they will do with it */
+ }
+ 
+ /*
Index: pkgsrc/www/basilisk/patches/patch-platform_security_generate__mapfile.py
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_security_generate__mapfile.py:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_security_generate__mapfile.py    Fri Apr 25 21:25:03 2025
@@ -0,0 +1,26 @@
+$NetBSD: patch-platform_security_generate__mapfile.py,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Add NetBSD support.
+
+--- platform/security/generate_mapfile.py.orig 2024-07-25 11:47:02.692533986 +0000
++++ platform/security/generate_mapfile.py
+@@ -17,10 +17,10 @@ import buildconfig
+ 
+ 
+ def main(output, input):
+-    if buildconfig.substs['OS_ARCH'] not in ('Linux', 'SunOS', 'Darwin', 'FreeBSD'):
++    if buildconfig.substs['OS_ARCH'] not in ('Linux', 'SunOS', 'Darwin', 'FreeBSD', 'NetBSD'):
+         print "Error: unhandled OS_ARCH %s" % buildconfig.substs['OS_ARCH']
+         return 1
+-    is_linux = buildconfig.substs['OS_ARCH'] in ('Linux', 'SunOS', 'FreeBSD')
++    is_linux = buildconfig.substs['OS_ARCH'] in ('Linux', 'SunOS', 'FreeBSD', 'NetBSD')
+ 
+     with open(input, 'rb') as f:
+         for line in f:
+@@ -49,4 +49,4 @@ def main(output, input):
+             if line and not is_linux:
+                 output.write('_')
+             output.write(line)
+-            output.write('\n')
+\ No newline at end of file
++            output.write('\n')
Index: pkgsrc/www/basilisk/patches/patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops.h
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops.h:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops.h        Fri Apr 25 21:25:03 2025
@@ -0,0 +1,26 @@
+$NetBSD: patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops.h,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Fixes for NetBSD/arm, taken from www/firefox52
+
+--- platform/toolkit/components/protobuf/src/google/protobuf/stubs/atomicops.h.orig    2024-07-10 08:54:53.000000000 +0000
++++ platform/toolkit/components/protobuf/src/google/protobuf/stubs/atomicops.h
+@@ -76,6 +76,11 @@ typedef intptr_t Atomic64;
+ #endif
+ #endif
+ 
++#if defined(__NetBSD__) && defined(__arm__)
++// NetBSD/arm uses long for intptr_t, which fails -fpermissive checks. So
++// explicitly use int32 here instead.
++typedef int32 AtomicWord;
++#else
+ // Use AtomicWord for a machine-sized pointer.  It will use the Atomic32 or
+ // Atomic64 routines below, depending on your architecture.
+ #if defined(__OpenBSD__) && !defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+@@ -83,6 +88,7 @@ typedef Atomic32 AtomicWord;
+ #else
+ typedef intptr_t AtomicWord;
+ #endif
++#endif
+ 
+ // Atomically execute:
+ //      result = *ptr;
Index: pkgsrc/www/basilisk/patches/patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops__internals__arm__gcc.h
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops__internals__arm__gcc.h:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops__internals__arm__gcc.h   Fri Apr 25 21:25:03 2025
@@ -0,0 +1,91 @@
+$NetBSD: patch-platform_toolkit_components_protobuf_src_google_protobuf_stubs_atomicops__internals__arm__gcc.h,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Fixes for NetBSD/arm, taken from www/firefox52
+
+--- platform/toolkit/components/protobuf/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h.orig  2024-07-10 08:54:53.000000000 +0000
++++ platform/toolkit/components/protobuf/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h
+@@ -39,44 +39,19 @@ namespace google {
+ namespace protobuf {
+ namespace internal {
+ 
+-// 0xffff0fc0 is the hard coded address of a function provided by
+-// the kernel which implements an atomic compare-exchange. On older
+-// ARM architecture revisions (pre-v6) this may be implemented using
+-// a syscall. This address is stable, and in active use (hard coded)
+-// by at least glibc-2.7 and the Android C library.
+-typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value,
+-                                           Atomic32 new_value,
+-                                           volatile Atomic32* ptr);
+-LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) =
+-    (LinuxKernelCmpxchgFunc) 0xffff0fc0;
+-
+-typedef void (*LinuxKernelMemoryBarrierFunc)(void);
+-LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) =
+-    (LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
+-
+-
+ inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                          Atomic32 old_value,
+                                          Atomic32 new_value) {
+-  Atomic32 prev_value = *ptr;
+-  do {
+-    if (!pLinuxKernelCmpxchg(old_value, new_value,
+-                             const_cast<Atomic32*>(ptr))) {
+-      return old_value;
+-    }
+-    prev_value = *ptr;
+-  } while (prev_value == old_value);
+-  return prev_value;
++  return __sync_val_compare_and_swap(ptr, old_value, new_value);
+ }
+ 
+ inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                          Atomic32 new_value) {
+-  Atomic32 old_value;
++  Atomic32 prev_value;
+   do {
+-    old_value = *ptr;
+-  } while (pLinuxKernelCmpxchg(old_value, new_value,
+-                               const_cast<Atomic32*>(ptr)));
+-  return old_value;
++    prev_value = *ptr;
++  } while (!__sync_bool_compare_and_swap(ptr, prev_value, new_value));
++  return prev_value;
+ }
+ 
+ inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+@@ -86,17 +61,15 @@ inline Atomic32 NoBarrier_AtomicIncremen
+ 
+ inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                         Atomic32 increment) {
+-  for (;;) {
++  Atomic32 old_value;
++  Atomic32 new_value;
++
++  do {
+     // Atomic exchange the old value with an incremented one.
+-    Atomic32 old_value = *ptr;
+-    Atomic32 new_value = old_value + increment;
+-    if (pLinuxKernelCmpxchg(old_value, new_value,
+-                            const_cast<Atomic32*>(ptr)) == 0) {
+-      // The exchange took place as expected.
+-      return new_value;
+-    }
+-    // Otherwise, *ptr changed mid-loop and we need to retry.
+-  }
++    old_value = *ptr;
++    new_value = old_value + increment;
++  } while (!__sync_bool_compare_and_swap(ptr, old_value, new_value));
++  return new_value;
+ }
+ 
+ inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+@@ -116,7 +89,7 @@ inline void NoBarrier_Store(volatile Ato
+ }
+ 
+ inline void MemoryBarrier() {
+-  pLinuxKernelMemoryBarrier();
++  __sync_synchronize();
+ }
+ 
+ inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
Index: pkgsrc/www/basilisk/patches/patch-platform_toolkit_xre_nsX11ErrorHandler.cpp
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_toolkit_xre_nsX11ErrorHandler.cpp:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_toolkit_xre_nsX11ErrorHandler.cpp        Fri Apr 25 21:25:03 2025
@@ -0,0 +1,23 @@
+$NetBSD: patch-platform_toolkit_xre_nsX11ErrorHandler.cpp,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Switch NS_RUNTIMEABORT to NS_WARNING to avoid crash seen on NetBSD with
+"X_CopyArea: BadDrawable (invalid Pixmap or Window parameter);"
+
+--- platform/toolkit/xre/nsX11ErrorHandler.cpp.orig    2024-07-10 08:54:53.000000000 +0000
++++ platform/toolkit/xre/nsX11ErrorHandler.cpp
+@@ -131,7 +131,14 @@ X11Error(Display *display, XErrorEvent *
+ #endif
+ #endif
+ 
+-  NS_RUNTIMEABORT(notes.get());
++  if (message.EqualsLiteral("62")) { // 62 == X_CopyArea
++    // Avoid NS_RUNTIMEABORT seen on NetBSD with
++    // "X_CopyArea: BadDrawable (invalid Pixmap or Window parameter);"
++    NS_WARNING(notes.get());
++  } else {
++    NS_RUNTIMEABORT(notes.get());
++  }
++
+   return 0; // not reached
+ }
+ }
Index: pkgsrc/www/basilisk/patches/patch-platform_xpcom_reflect_xptcall_md_unix_xptcinvoke__arm__netbsd.cpp
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_xpcom_reflect_xptcall_md_unix_xptcinvoke__arm__netbsd.cpp:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_xpcom_reflect_xptcall_md_unix_xptcinvoke__arm__netbsd.cpp        Fri Apr 25 21:25:03 2025
@@ -0,0 +1,529 @@
+$NetBSD: patch-platform_xpcom_reflect_xptcall_md_unix_xptcinvoke__arm__netbsd.cpp,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Update code to fix NetBSD/arm. Copied from www/firefox52.
+
+--- platform/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp.orig      2024-07-10 08:54:53.000000000 +0000
++++ platform/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp
+@@ -7,82 +7,92 @@
+ 
+ #include "xptcprivate.h"
+ 
+-// Remember that these 'words' are 32bit DWORDS
++#include "mozilla/Compiler.h"
+ 
+-static uint32_t
+-invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
++#ifndef __ARM_PCS_VFP
++
++/* This function copies a 64-bits word from dw to the given pointer in
++ * a buffer delimited by start and end, possibly wrapping around the
++ * buffer boundaries, and/or properly aligning the data at 64-bits word
++ * boundaries (for EABI).
++ * start and end are both assumed to be 64-bits aligned.
++ * Returns a pointer to the second 32-bits word copied (to accomodate
++ * the invoke_copy_to_stack loop).
++ */
++static uint32_t *
++copy_double_word(uint32_t *start, uint32_t *current, uint32_t *end, uint64_t *dw)
+ {
+-    uint32_t result = 0;
+-    for(uint32_t i = 0; i < paramCount; i++, s++)
+-    {
+-        if(s->IsPtrData())
+-        {
+-            result++;
+-            continue;
+-        }
+-        switch(s->type)
+-        {
+-        case nsXPTType::T_I8     :
+-        case nsXPTType::T_I16    :
+-        case nsXPTType::T_I32    :
+-            result++;
+-            break;
+-        case nsXPTType::T_I64    :
+-            result+=2;
+-            break;
+-        case nsXPTType::T_U8     :
+-        case nsXPTType::T_U16    :
+-        case nsXPTType::T_U32    :
+-            result++;
+-            break;
+-        case nsXPTType::T_U64    :
+-            result+=2;
+-            break;
+-        case nsXPTType::T_FLOAT  :
+-            result++;
+-            break;
+-        case nsXPTType::T_DOUBLE :
+-            result+=2;
+-            break;
+-        case nsXPTType::T_BOOL   :
+-        case nsXPTType::T_CHAR   :
+-        case nsXPTType::T_WCHAR  :
+-            result++;
+-            break;
+-        default:
+-            // all the others are plain pointer types
+-            result++;
+-            break;
+-        }
++#ifdef __ARM_EABI__
++    /* Aligning the pointer for EABI */
++    current = (uint32_t *)(((uint32_t)current + 7) & ~7);
++    /* Wrap when reaching the end of the buffer */
++    if (current == end) current = start;
++#else
++    /* On non-EABI, 64-bits values are not aligned and when we reach the end
++     * of the buffer, we need to write half of the data at the end, and the
++     * other half at the beginning. */
++    if (current == end - 1) {
++        *current = ((uint32_t*)dw)[0];
++        *start = ((uint32_t*)dw)[1];
++        return start;
+     }
+-    return result;
++#endif
++
++    *((uint64_t*) current) = *dw;
++    return current + 1;
+ }
+ 
+-static void
+-invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
++/* See stack_space comment in NS_InvokeByIndex to see why this needs not to
++ * be static on DEBUG builds. */
++#ifndef DEBUG
++static
++#endif
++void
++invoke_copy_to_stack(uint32_t* stk, uint32_t *end,
++                     uint32_t paramCount, nsXPTCVariant* s)
+ {
++    /* The stack buffer is 64-bits aligned. The end argument points to its end.
++     * The caller is assumed to create a stack buffer of at least four 32-bits
++     * words.
++     * We use the last three 32-bit words to store the values for r1, r2 and r3
++     * for the method call, i.e. the first words for arguments passing.
++     */
++    uint32_t *d = end - 3;
+     for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+     {
++        /* Wrap when reaching the end of the stack buffer */
++        if (d == end) d = stk;
++        NS_ASSERTION(d >= stk && d < end,
++            "invoke_copy_to_stack is copying outside its given buffer");
+         if(s->IsPtrData())
+         {
+             *((void**)d) = s->ptr;
+             continue;
+         }
++        // According to the ARM EABI, integral types that are smaller than a word
++        // are to be sign/zero-extended to a full word and treated as 4-byte values.
++
+         switch(s->type)
+         {
+-        case nsXPTType::T_I8     : *((int8_t*)  d) = s->val.i8;          break;
+-        case nsXPTType::T_I16    : *((int16_t*) d) = s->val.i16;         break;
++        case nsXPTType::T_I8     : *((int32_t*) d) = s->val.i8;          break;
++        case nsXPTType::T_I16    : *((int32_t*) d) = s->val.i16;         break;
+         case nsXPTType::T_I32    : *((int32_t*) d) = s->val.i32;         break;
+-        case nsXPTType::T_I64    : *((int64_t*) d) = s->val.i64; d++;    break;
+-        case nsXPTType::T_U8     : *((uint8_t*) d) = s->val.u8;          break;
+-        case nsXPTType::T_U16    : *((uint16_t*)d) = s->val.u16;         break;
++        case nsXPTType::T_I64    :
++            d = copy_double_word(stk, d, end, (uint64_t *)&s->val.i64);
++            break;
++        case nsXPTType::T_U8     : *((uint32_t*)d) = s->val.u8;          break;
++        case nsXPTType::T_U16    : *((uint32_t*)d) = s->val.u16;         break;
+         case nsXPTType::T_U32    : *((uint32_t*)d) = s->val.u32;         break;
+-        case nsXPTType::T_U64    : *((uint64_t*)d) = s->val.u64; d++;    break;
++        case nsXPTType::T_U64    :
++            d = copy_double_word(stk, d, end, (uint64_t *)&s->val.u64);
++            break;
+         case nsXPTType::T_FLOAT  : *((float*)   d) = s->val.f;           break;
+-        case nsXPTType::T_DOUBLE : *((double*)  d) = s->val.d;   d++;    break;
+-        case nsXPTType::T_BOOL   : *((bool*)  d) = s->val.b;           break;
+-        case nsXPTType::T_CHAR   : *((char*)    d) = s->val.c;           break;
+-        case nsXPTType::T_WCHAR  : *((wchar_t*) d) = s->val.wc;          break;
++        case nsXPTType::T_DOUBLE :
++            d = copy_double_word(stk, d, end, (uint64_t *)&s->val.d);
++            break;
++        case nsXPTType::T_BOOL   : *((int32_t*) d) = s->val.b;           break;
++        case nsXPTType::T_CHAR   : *((int32_t*) d) = s->val.c;           break;
++        case nsXPTType::T_WCHAR  : *((int32_t*) d) = s->val.wc;          break;
+         default:
+             // all the others are plain pointer types
+             *((void**)d) = s->val.p;
+@@ -91,47 +101,27 @@ invoke_copy_to_stack(uint32_t* d, uint32
+     }
+ }
+ 
+-extern "C" 
+-struct my_params_struct {
+-    nsISupports* that;      
+-    uint32_t Index;         
+-    uint32_t Count;         
+-    nsXPTCVariant* params;  
+-    uint32_t fn_count;     
+-    uint32_t fn_copy;      
+-};
++typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t);
+ 
+-XPTC_PUBLIC_API(nsresult)
+-XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
++EXPORT_XPCOM_API(nsresult)
++NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+                    uint32_t paramCount, nsXPTCVariant* params)
+ {
+-    uint32_t result;
+-    struct my_params_struct my_params;
+-    my_params.that = that;
+-    my_params.Index = methodIndex;
+-    my_params.Count = paramCount;
+-    my_params.params = params;
+-    my_params.fn_copy = (uint32_t) &invoke_copy_to_stack;
+-    my_params.fn_count = (uint32_t) &invoke_count_words;
+ 
+ /* This is to call a given method of class that.
+  * The parameters are in params, the number is in paramCount.
+  * The routine will issue calls to count the number of words
+  * required for argument passing and to copy the arguments to
+  * the stack.
+- * Since APCS passes the first 3 params in r1-r3, we need to
+- * load the first three words from the stack and correct the stack
+- * pointer (sp) in the appropriate way. This means:
+- *
+- * 1.) more than 3 arguments: load r1-r3, correct sp and remember No.
+- *                          of bytes left on the stack in r4
+- *
+- * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope),
+- *              restore sp as if nothing had happened and set the marker r4 to zero.
+- *
+- * Afterwards sp will be restored using the value in r4 (which is not a temporary register
+- * and will be preserved by the function/method called according to APCS [ARM Procedure
+- * Calling Standard]).
++ * ACPS passes the first 3 params in r1-r3 (with exceptions for 64-bits
++ * arguments), and the remaining goes onto the stack.
++ * We allocate a buffer on the stack for a "worst case" estimate of how much
++ * stack might be needed for EABI, i.e. twice the number of parameters.
++ * The end of this buffer will be used to store r1 to r3, so that the start
++ * of the stack is the remaining parameters.
++ * The magic here is to call the method with "that" and three 32-bits
++ * arguments corresponding to r1-r3, so that the compiler generates the
++ * proper function call. The stack will also contain the remaining arguments.
+  *
+  * !!! IMPORTANT !!!
+  * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
+@@ -139,43 +129,272 @@ XPTC_InvokeByIndex(nsISupports* that, ui
+  *
+  */
+  
+-  __asm__ __volatile__(
+-    "ldr      r1, [%1, #12]   \n\t"   /* prepare to call invoke_count_words   */
+-    "ldr      ip, [%1, #16]   \n\t"   /* r0=paramCount, r1=params             */
+-    "ldr      r0, [%1,  #8]   \n\t"
+-    "mov      lr, pc          \n\t"   /* call it...                           */
+-    "mov      pc, ip          \n\t"
+-    "mov      r4, r0, lsl #2  \n\t"   /* This is the amount of bytes needed.  */
+-    "sub      sp, sp, r4      \n\t"   /* use stack space for the args...      */
+-    "mov      r0, sp          \n\t"   /* prepare a pointer an the stack       */
+-    "ldr      r1, [%1,  #8]   \n\t"   /* =paramCount                          */
+-    "ldr      r2, [%1, #12]   \n\t"   /* =params                              */
+-    "ldr      ip, [%1, #20]   \n\t"   /* =invoke_copy_to_stack                */
+-    "mov      lr, pc          \n\t"   /* copy args to the stack like the      */
+-    "mov      pc, ip          \n\t"   /* compiler would.                      */
+-    "ldr      r0, [%1]        \n\t"   /* =that                                */
+-    "ldr      r1, [r0, #0]    \n\t"   /* get that->vtable offset              */
+-    "ldr      r2, [%1, #4]    \n\t"
+-    "add      r2, r1, r2, lsl #3\n\t" /* a vtable_entry(x)=8 + (8 bytes * x)  */
+-    "add      r2, r2, #8      \n\t"   /* with this compilers                  */
+-    "ldr      r3, [r2]        \n\t"   /* get virtual offset from vtable       */
+-    "mov      r3, r3, lsl #16 \n\t"
+-    "add      r0, r0, r3, asr #16\n\t"
+-    "ldr      ip, [r2, #4]    \n\t"   /* get method address from vtable       */
+-    "cmp      r4, #12         \n\t"   /* more than 3 arguments???             */
+-    "ldmgtia  sp!, {r1, r2, r3}\n\t"  /* yes: load arguments for r1-r3        */
+-    "subgt    r4, r4, #12     \n\t"   /*      and correct the stack pointer   */
+-    "ldmleia  sp, {r1, r2, r3}\n\t"   /* no:  load r1-r3 from stack           */ 
+-    "addle    sp, sp, r4      \n\t"   /*      and restore stack pointer       */
+-    "movle    r4, #0          \n\t"   /*      a mark for restoring sp         */
+-    "mov      lr, pc          \n\t"   /* call mathod                          */
+-    "mov      pc, ip          \n\t"
+-    "add      sp, sp, r4      \n\t"   /* restore stack pointer                */
+-    "mov      %0, r0          \n\t"   /* the result...                        */
+-    : "=r" (result)
+-    : "r" (&my_params)
+-    : "r0", "r1", "r2", "r3", "r4", "ip", "lr"
+-    );
+-    
+-  return result;
++  vtable_func *vtable, func;
++  int base_size = (paramCount > 1) ? paramCount : 2;
++
++/* !!! IMPORTANT !!!
++ * On DEBUG builds, the NS_ASSERTION used in invoke_copy_to_stack needs to use
++ * the stack to pass the 5th argument to NS_DebugBreak. When invoke_copy_to_stack
++ * is inlined, this can result, depending on the compiler and flags, in the
++ * stack pointer not pointing at stack_space when the method is called at the
++ * end of this function. More generally, any function call requiring stack
++ * allocation of arguments is unsafe to be inlined in this function.
++ */
++  uint32_t *stack_space = (uint32_t *) __builtin_alloca(base_size * 8);
++
++  invoke_copy_to_stack(stack_space, &stack_space[base_size * 2],
++                       paramCount, params);
++
++  vtable = *reinterpret_cast<vtable_func **>(that);
++  func = vtable[methodIndex];
++
++  return func(that, stack_space[base_size * 2 - 3],
++                    stack_space[base_size * 2 - 2],
++                    stack_space[base_size * 2 - 1]);
+ }    
++
++#else /* __ARM_PCS_VFP */
++
++/* "Procedure Call Standard for the ARM Architecture" document, sections
++ * "5.5 Parameter Passing" and "6.1.2 Procedure Calling" contain all the
++ * needed information.
++ *
++ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
++ */
++
++#if defined(__thumb__) && !defined(__thumb2__)
++#error "Thumb1 is not supported"
++#endif
++
++#ifndef __ARMEL__
++#error "Only little endian compatibility was tested"
++#endif
++
++/*
++ * Allocation of integer function arguments initially to registers r1-r3
++ * and then to stack. Handling of 'this' argument which goes to r0 registers
++ * is handled separately and does not belong to these two inline functions.
++ *
++ * The doubleword arguments are allocated to even:odd
++ * register pairs or get aligned at 8-byte boundary on stack. The "holes"
++ * which may appear as a result of this realignment remain unused.
++ *
++ * 'ireg_args'  - pointer to the current position in the buffer,
++ *                corresponding to the register arguments
++ * 'stack_args' - pointer to the current position in the buffer,
++ *                corresponding to the arguments on stack
++ * 'end'        - pointer to the end of the registers argument
++ *                buffer (it is guaranteed to be 8-bytes aligned)
++ */
++
++static inline void copy_word(uint32_t* &ireg_args,
++                             uint32_t* &stack_args,
++                             uint32_t* end,
++                             uint32_t  data)
++{
++  if (ireg_args < end) {
++    *ireg_args = data;
++    ireg_args++;
++  } else {
++    *stack_args = data;
++    stack_args++;
++  }
++}
++
++static inline void copy_dword(uint32_t* &ireg_args,
++                              uint32_t* &stack_args,
++                              uint32_t* end,
++                              uint64_t  data)
++{
++  if (ireg_args + 1 < end) {
++    if ((uint32_t)ireg_args & 4) {
++      ireg_args++;
++    }
++    *(uint64_t *)ireg_args = data;
++    ireg_args += 2;
++  } else {
++    if ((uint32_t)stack_args & 4) {
++      stack_args++;
++    }
++    *(uint64_t *)stack_args = data;
++    stack_args += 2;
++  }
++}
++
++/*
++ * Allocation of floating point arguments to VFP registers (s0-s15, d0-d7).
++ *
++ * Unlike integer registers allocation, "back-filling" needs to be
++ * supported. For example, the third floating point argument in the
++ * following function is going to be allocated to s1 register, back-filling
++ * the "hole":
++ *    void f(float s0, double d1, float s1)
++ *
++ * Refer to the "Procedure Call Standard for the ARM Architecture" document
++ * for more details.
++ *
++ * 'vfp_s_args' - pointer to the current position in the buffer with
++ *                the next unallocated single precision register
++ * 'vfp_d_args' - pointer to the current position in the buffer with
++ *                the next unallocated double precision register,
++ *                it has the same value as 'vfp_s_args' when back-filling
++ *                is not used
++ * 'end'        - pointer to the end of the vfp registers argument
++ *                buffer (it is guaranteed to be 8-bytes aligned)
++ *
++ * Mozilla bugtracker has a test program attached which be used for
++ * experimenting with VFP registers allocation code and testing its
++ * correctness:
++ * https://bugzilla.mozilla.org/show_bug.cgi?id=601914#c19
++ */
++
++static inline bool copy_vfp_single(float* &vfp_s_args, double* &vfp_d_args,
++                                   float* end, float data)
++{
++  if (vfp_s_args >= end)
++    return false;
++
++  *vfp_s_args = data;
++  vfp_s_args++;
++  if (vfp_s_args < (float *)vfp_d_args) {
++    // It was the case of back-filling, now the next free single precision
++    // register should overlap with the next free double precision register
++    vfp_s_args = (float *)vfp_d_args;
++  } else if (vfp_s_args > (float *)vfp_d_args) {
++    // also update the pointer to the next free double precision register
++    vfp_d_args++;
++  }
++  return true;
++}
++
++static inline bool copy_vfp_double(float* &vfp_s_args, double* &vfp_d_args,
++                                   float* end, double data)
++{
++  if (vfp_d_args >= (double *)end) {
++    // The back-filling continues only so long as no VFP CPRC has been
++    // allocated to a slot on the stack. Basically no VFP registers can
++    // be allocated after this point.
++    vfp_s_args = end;
++    return false;
++  }
++
++  if (vfp_s_args == (float *)vfp_d_args) {
++    // also update the pointer to the next free single precision register
++    vfp_s_args += 2;
++  }
++  *vfp_d_args = data;
++  vfp_d_args++;
++  return true;
++}
++
++static void
++invoke_copy_to_stack(uint32_t* stk, uint32_t *end,
++                     uint32_t paramCount, nsXPTCVariant* s)
++{
++  uint32_t *ireg_args  = end - 3;
++  float    *vfp_s_args = (float *)end;
++  double   *vfp_d_args = (double *)end;
++  float    *vfp_end    = vfp_s_args + 16;
++
++  for (uint32_t i = 0; i < paramCount; i++, s++) {
++    if (s->IsPtrData()) {
++      copy_word(ireg_args, stk, end, (uint32_t)s->ptr);
++      continue;
++    }
++    // According to the ARM EABI, integral types that are smaller than a word
++    // are to be sign/zero-extended to a full word and treated as 4-byte values
++    switch (s->type)
++    {
++      case nsXPTType::T_FLOAT:
++        if (!copy_vfp_single(vfp_s_args, vfp_d_args, vfp_end, s->val.f)) {
++          copy_word(end, stk, end, reinterpret_cast<uint32_t&>(s->val.f));
++        }
++        break;
++      case nsXPTType::T_DOUBLE:
++        if (!copy_vfp_double(vfp_s_args, vfp_d_args, vfp_end, s->val.d)) {
++          copy_dword(end, stk, end, reinterpret_cast<uint64_t&>(s->val.d));
++        }
++        break;
++      case nsXPTType::T_I8:  copy_word(ireg_args, stk, end, s->val.i8);   break;
++      case nsXPTType::T_I16: copy_word(ireg_args, stk, end, s->val.i16);  break;
++      case nsXPTType::T_I32: copy_word(ireg_args, stk, end, s->val.i32);  break;
++      case nsXPTType::T_I64: copy_dword(ireg_args, stk, end, s->val.i64); break;
++      case nsXPTType::T_U8:  copy_word(ireg_args, stk, end, s->val.u8);   break;
++      case nsXPTType::T_U16: copy_word(ireg_args, stk, end, s->val.u16);  break;
++      case nsXPTType::T_U32: copy_word(ireg_args, stk, end, s->val.u32);  break;
++      case nsXPTType::T_U64: copy_dword(ireg_args, stk, end, s->val.u64); break;
++      case nsXPTType::T_BOOL: copy_word(ireg_args, stk, end, s->val.b);   break;
++      case nsXPTType::T_CHAR: copy_word(ireg_args, stk, end, s->val.c);   break;
++      case nsXPTType::T_WCHAR: copy_word(ireg_args, stk, end, s->val.wc); break;
++      default:
++        // all the others are plain pointer types
++        copy_word(ireg_args, stk, end, reinterpret_cast<uint32_t>(s->val.p));
++        break;
++    }
++  }
++}
++
++typedef uint32_t (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t);
++
++EXPORT_XPCOM_API(nsresult)
++NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
++                   uint32_t paramCount, nsXPTCVariant* params)
++{
++  vtable_func *vtable = *reinterpret_cast<vtable_func **>(that);
++  vtable_func func = vtable[methodIndex];
++  // 'register uint32_t result asm("r0")' could be used here, but it does not
++  //  seem to be reliable in all cases: http://gcc.gnu.org/PR46164
++  nsresult result;
++  asm (
++    "mov    r3, sp\n"
++    "mov    %[stack_space_size], %[param_count_plus_2], lsl #3\n"
++    "tst    r3, #4\n" /* check stack alignment */
++
++    "add    %[stack_space_size], #(4 * 16)\n" /* space for VFP registers */
++    "mov    r3, %[params]\n"
++
++    "it     ne\n"
++    "addne  %[stack_space_size], %[stack_space_size], #4\n"
++    "sub    r0, sp, %[stack_space_size]\n" /* allocate space on stack */
++
++    "sub    r2, %[param_count_plus_2], #2\n"
++    "mov    sp, r0\n"
++
++    "add    r1, r0, %[param_count_plus_2], lsl #3\n"
++    "blx    %[invoke_copy_to_stack]\n"
++
++    "add    ip, sp, %[param_count_plus_2], lsl #3\n"
++    "mov    r0, %[that]\n"
++    "ldmdb  ip, {r1, r2, r3}\n"
++    "vldm   ip, {d0, d1, d2, d3, d4, d5, d6, d7}\n"
++    "blx    %[func]\n"
++
++    "add    sp, sp, %[stack_space_size]\n" /* cleanup stack */
++    "mov    %[stack_space_size], r0\n" /* it's actually 'result' variable */
++    : [stack_space_size]     "=&r" (result)
++    : [func]                 "r"   (func),
++      [that]                 "r"   (that),
++      [params]               "r"   (params),
++      [param_count_plus_2]   "r"   (paramCount + 2),
++      [invoke_copy_to_stack] "r"   (invoke_copy_to_stack)
++    : "cc", "memory",
++      // Mark all the scratch registers as clobbered because they may be
++      // modified by the functions, called from this inline assembly block
++      "r0", "r1", "r2", "r3", "ip", "lr",
++      "d0",  "d1",  "d2",  "d3",  "d4",  "d5",  "d6",  "d7",
++      // Also unconditionally mark d16-d31 registers as clobbered even though
++      // they actually don't exist in vfpv2 and vfpv3-d16 variants. There is
++      // no way to identify VFP variant using preprocessor at the momemnt
++      // (see http://gcc.gnu.org/PR46128 for more details), but fortunately
++      // current versions of gcc do not seem to complain about these registers
++      // even when this code is compiled with '-mfpu=vfpv3-d16' option.
++      // If gcc becomes more strict in the future and/or provides a way to
++      // identify VFP variant, the following d16-d31 registers list needs
++      // to be wrapped into some #ifdef
++      "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
++      "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"
++  );
++  return result;
++}
++
++#endif
Index: pkgsrc/www/basilisk/patches/patch-platform_xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp
diff -u /dev/null pkgsrc/www/basilisk/patches/patch-platform_xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp:1.1
--- /dev/null   Fri Apr 25 21:25:03 2025
+++ pkgsrc/www/basilisk/patches/patch-platform_xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp Fri Apr 25 21:25:03 2025
@@ -0,0 +1,219 @@
+$NetBSD: patch-platform_xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp,v 1.1 2025/04/25 21:25:03 nia Exp $
+
+Update code to fix NetBSD/arm. Copied from www/firefox52.
+
+--- platform/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp.orig       2024-07-10 08:54:53.000000000 +0000
++++ platform/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp
+@@ -6,15 +6,32 @@
+ /* Implement shared vtbl methods. */
+ 
+ #include "xptcprivate.h"
++#include "xptiprivate.h"
+ 
+-nsresult ATTRIBUTE_USED
++/* Specify explicitly a symbol for this function, don't try to guess the c++ mangled symbol.  */
++static nsresult PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) asm("_PrepareAndDispatch")
++ATTRIBUTE_USED;
++
++#ifdef __ARM_EABI__
++#define DOUBLEWORD_ALIGN(p) ((uint32_t *)((((uint32_t)(p)) + 7) & 0xfffffff8))
++#else
++#define DOUBLEWORD_ALIGN(p) (p)
++#endif
++
++// Apple's iOS toolchain is lame and does not support .cfi directives.
++#ifdef __APPLE__
++#define CFI(str)
++#else
++#define CFI(str) str
++#endif
++
++static nsresult
+ PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+ {
+ #define PARAM_BUFFER_COUNT     16
+ 
+     nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+     nsXPTCMiniVariant* dispatchParams = nullptr;
+-    nsIInterfaceInfo* iface_info = nullptr;
+     const nsXPTMethodInfo* info;
+     uint8_t paramCount;
+     uint8_t i;
+@@ -22,12 +39,7 @@ PrepareAndDispatch(nsXPTCStubBase* self,
+ 
+     NS_ASSERTION(self,"no self");
+ 
+-    self->GetInterfaceInfo(&iface_info);
+-    NS_ASSERTION(iface_info,"no interface info");
+-
+-    iface_info->GetMethodInfo(uint16_t(methodIndex), &info);
+-    NS_ASSERTION(info,"no interface info");
+-
++    self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+     paramCount = info->GetParamCount();
+ 
+     // setup variant array pointer
+@@ -55,13 +67,16 @@ PrepareAndDispatch(nsXPTCStubBase* self,
+         case nsXPTType::T_I8     : dp->val.i8  = *((int8_t*)  ap);       break;
+         case nsXPTType::T_I16    : dp->val.i16 = *((int16_t*) ap);       break;
+         case nsXPTType::T_I32    : dp->val.i32 = *((int32_t*) ap);       break;
+-        case nsXPTType::T_I64    : dp->val.i64 = *((int64_t*) ap); ap++; break;
++        case nsXPTType::T_I64    : ap = DOUBLEWORD_ALIGN(ap);
++                                 dp->val.i64 = *((int64_t*) ap); ap++; break;
+         case nsXPTType::T_U8     : dp->val.u8  = *((uint8_t*) ap);       break;
+         case nsXPTType::T_U16    : dp->val.u16 = *((uint16_t*)ap);       break;
+         case nsXPTType::T_U32    : dp->val.u32 = *((uint32_t*)ap);       break;
+-        case nsXPTType::T_U64    : dp->val.u64 = *((uint64_t*)ap); ap++; break;
++        case nsXPTType::T_U64    : ap = DOUBLEWORD_ALIGN(ap);
++                                 dp->val.u64 = *((uint64_t*)ap); ap++; break;
+         case nsXPTType::T_FLOAT  : dp->val.f   = *((float*)   ap);       break;
+-        case nsXPTType::T_DOUBLE : dp->val.d   = *((double*)  ap); ap++; break;
++        case nsXPTType::T_DOUBLE : ap = DOUBLEWORD_ALIGN(ap);
++                                 dp->val.d   = *((double*)  ap); ap++; break;
+         case nsXPTType::T_BOOL   : dp->val.b   = *((bool*)  ap);       break;
+         case nsXPTType::T_CHAR   : dp->val.c   = *((char*)    ap);       break;
+         case nsXPTType::T_WCHAR  : dp->val.wc  = *((wchar_t*) ap);       break;
+@@ -71,9 +86,7 @@ PrepareAndDispatch(nsXPTCStubBase* self,
+         }
+     }
+ 
+-    result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+-
+-    NS_RELEASE(iface_info);
++    result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+ 
+     if(dispatchParams != paramBuffer)
+         delete [] dispatchParams;
+@@ -82,26 +95,114 @@ PrepareAndDispatch(nsXPTCStubBase* self,
+ }
+ 
+ /*
+- * These stubs move just move the values passed in registers onto the stack,
+- * so they are contiguous with values passed on the stack, and then calls
+- * PrepareAndDispatch() to do the dirty work.
++ * This is our shared stub.
++ *
++ * r0 = Self.
++ *
++ * The Rules:
++ *   We pass an (undefined) number of arguments into this function.
++ *   The first 3 C++ arguments are in r1 - r3, the rest are built
++ *   by the calling function on the stack.
++ *
++ *   We are allowed to corrupt r0 - r3, ip, and lr.
++ *
++ * Other Info:
++ *   We pass the stub number in using `ip'.
++ *
++ * Implementation:
++ * - We save r1 to r3 inclusive onto the stack, which will be
++ *   immediately below the caller saved arguments.
++ * - setup r2 (PrepareAndDispatch's args pointer) to point at
++ *   the base of all these arguments
++ * - Save LR (for the return address)
++ * - Set r1 (PrepareAndDispatch's methodindex argument) from ip
++ * - r0 is passed through (self)
++ * - Call PrepareAndDispatch
++ * - When the call returns, we return by loading the PC off the
++ *   stack, and undoing the stack (one instruction)!
++ *
+  */
++__asm__ ("\n"
++         ".text\n"
++         ".align 2\n"
++         "SharedStub:\n"
++         CFI(".cfi_startproc\n")
++         "stmfd       sp!, {r1, r2, r3}\n"
++         CFI(".cfi_def_cfa_offset 12\n")
++         CFI(".cfi_offset r3, -4\n")
++         CFI(".cfi_offset r2, -8\n")
++         CFI(".cfi_offset r1, -12\n")
++         "mov r2, sp\n"
++         "str lr, [sp, #-4]!\n"
++         CFI(".cfi_def_cfa_offset 16\n")
++         CFI(".cfi_offset lr, -16\n")
++         "mov r1, ip\n"
++         "bl  _PrepareAndDispatch\n"
++         "ldr pc, [sp], #16\n"
++         CFI(".cfi_endproc\n"));
++
++/*
++ * Create sets of stubs to call the SharedStub.
++ * We don't touch the stack here, nor any registers, other than IP.
++ * IP is defined to be corruptable by a called function, so we are
++ * safe to use it.
++ *
++ * This will work with or without optimisation.
++ */
++
++/*
++ * Note : As G++3 ABI contains the length of the functionname in the
++ *  mangled name, it is difficult to get a generic assembler mechanism like
++ *  in the G++ 2.95 case.
++ *  Create names would be like :
++ *    _ZN14nsXPTCStubBase5Stub9Ev
++ *    _ZN14nsXPTCStubBase6Stub13Ev
++ *    _ZN14nsXPTCStubBase7Stub144Ev
++ *  Use the assembler directives to get the names right...
++ */
++
++#define STUB_ENTRY(n)                                         \
++  __asm__(                                                    \
++      ".section \".text\"\n"                                  \
++"     .align 2\n"                                             \
++"     .iflt ("#n" - 10)\n"                                    \
++"     .globl  _ZN14nsXPTCStubBase5Stub"#n"Ev\n"               \
++"     .type   _ZN14nsXPTCStubBase5Stub"#n"Ev,#function\n"     \
++"_ZN14nsXPTCStubBase5Stub"#n"Ev:\n"                           \
++"     .else\n"                                                \
++"     .iflt  ("#n" - 100)\n"                                  \
++"     .globl  _ZN14nsXPTCStubBase6Stub"#n"Ev\n"               \
++"     .type   _ZN14nsXPTCStubBase6Stub"#n"Ev,#function\n"     \
++"_ZN14nsXPTCStubBase6Stub"#n"Ev:\n"                           \
++"     .else\n"                                                \
++"     .iflt ("#n" - 1000)\n"                                  \
++"     .globl  _ZN14nsXPTCStubBase7Stub"#n"Ev\n"               \
++"     .type   _ZN14nsXPTCStubBase7Stub"#n"Ev,#function\n"     \
++"_ZN14nsXPTCStubBase7Stub"#n"Ev:\n"                           \
++"     .else\n"                                                \
++"     .err \"stub number "#n"> 1000 not yet supported\"\n"    \
++"     .endif\n"                                               \
++"     .endif\n"                                               \
++"     .endif\n"                                               \
++"     mov     ip, #"#n"\n"                                    \
++"     b       SharedStub\n\t");
++
++#if 0
++/*
++ * This part is left in as comment : this is how the method definition
++ * should look like.
++ */
++
++#define STUB_ENTRY(n)  \
++nsresult nsXPTCStubBase::Stub##n ()  \
++{ \
++  __asm__ (                           \
++"     mov     ip, #"#n"\n"                                    \
++"     b       SharedStub\n\t");                               \
++  return 0; /* avoid warnings */                                \
++}
++#endif
+ 
+-#define STUB_ENTRY(n)                                                 \
+-__asm__(                                                              \
+-    ".global  _Stub"#n"__14nsXPTCStubBase\n\t"                        \
+-"_Stub"#n"__14nsXPTCStubBase:\n\t"                                    \
+-    "stmfd    sp!, {r1, r2, r3}       \n\t"                           \
+-    "mov      ip, sp                  \n\t"                           \
+-    "stmfd    sp!, {fp, ip, lr, pc}   \n\t"                           \
+-    "sub      fp, ip, #4              \n\t"                           \
+-    "mov      r1, #"#n"               \n\t"    /* = methodIndex       */ \
+-    "add      r2, sp, #16             \n\t"                           \
+-    "bl               _PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi   \n\t"    \
+-    "ldmea    fp, {fp, sp, lr}        \n\t"                           \
+-    "add      sp, sp, #12             \n\t"                           \
+-    "mov      pc, lr                  \n\t"                           \
+-);
+ 
+ #define SENTINEL_ENTRY(n) \
+ nsresult nsXPTCStubBase::Sentinel##n() \



Home | Main Index | Thread Index | Old Index