g29p1 Vulkan blob + Wayland for ODROID-M1 (C안) — full system matrix complete, release prep - #4
Conversation
…RNEL_SRCDIR dev mount from odroid-m1-panfrost These were found while bringing up the Panfrost (B) image but are generic bugfixes unrelated to which GPU stack the board uses: - rocknix-joypad/sdl3-x11 exclusion on this board was keyed off the blob package name (!BR2_PACKAGE_MALI_G52_ODROIDM1) as a stand-in for "this is the odroid-m1 board" - swapped to the always-present board identifier (BR2_PACKAGE_UBOOT_ODROID_M1) so it stays correct regardless of GPU stack. - TRX's desktop-GL requirement was similarly keyed off the blob package name instead of the real capability flag (BR2_PACKAGE_HAS_LIBGL). - moonlight-qt's guard is left untouched - its exclusion reason (a blob-specific eglGetPlatformDisplay gap) is genuinely GPU-driver-specific. - docker.mk's KERNEL_SRCDIR opt-in bind mount (buildroot's OVERRIDE_SRCDIR mechanism, see board/batocera/rockchip/bsp-odroidm1/local.mk.example on odroid-m1-panfrost) is harmless to have available on this branch too. No functional change for this branch's build output (blob still gates HAS_LIBGL/board-identity the same way as before), this is purely a root-cause correctness fix so the two branches don't drift on unrelated-to-GPU logic. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…6.1.5, matches mesa3d.mk/hash) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…ng the build host Confirmed via journalctl: the Claude Code process itself got OOM-killed mid-build (systemd: "ptyxis-spawn-...scope: A process of this unit has been killed by the OOM killer") while a from-scratch build was compiling MAME/OpenCV4/Kodi at BR2_JLEVEL=0's default (nproc+1=17 on this 16-core/ 15GB host) - wide parallelism multiplies peak per-translation-unit memory for large C++ files, not just wall-clock speed. odroid-m1-panfrost hit the same class of problem with LLVM+Mesa3D and already caps at 8; this board never got the equivalent cap despite also building large C++ codebases (this was the first from-scratch build of this board's output tree in a while, so the 17-way default had never actually been exercised under this kind of memory pressure before). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
~/git_projects no longer exists (2026-08-10 SSD swap moved everything to /mnt/2026_990pro_2tb_1_data/git_projects/, no symlink recreated on purpose per the migration handoff). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
Cherry-picked from odroid-m1-panfrost (B) where the comment correctly named that branch's kernel repo version. Track C stays on A's BSP kernel branch (fix-hdmi-dsi-dual-livelock), not panfrost-enable. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…side graph layered on top of each generator's existing fps display Single injection point (right where hud_support already sets MANGOHUD_DLSYM/MANGOHUD_CONFIGFILE) instead of touching every generator file individually - GALLIUM_HUD is a plain env var Mesa's gallium drivers read at process start, so it's a no-op on anything that never loads a gallium GL/GLES context (non-GL systems, the vendor Mali blob, older Mesa without HUD support). That makes it a natural fallback to each generator's own show_fps wiring (retroarch's fps_show, dolphin's ShowFPS, etc.) rather than requiring an either/or branch per emulator. Surfaced this session testing odroid-m1's Panfrost track: no numeric GPU-load metric is exposed anywhere on this kernel (no devfreq node - the GPU clock is statically pinned - no debugfs, and gallium_hud itself rejects the "GPU-load" query for this driver: "unknown driver query 'GPU-load'"), but the graph-based fps/frametime view was still strictly better than the existing plain-number counter for judging real-time performance during A/B testing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
Same change as odroid-m1-panfrost - global.powermode was never actually set in this board's default batocera.conf, so every A/B track fps measurement so far ran under batocera-power-mode's unset-fallback (set_default), not highperformance. Factory default only; ES's Game Settings > Power Mode menu still overrides it live. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
vkquake2 genuinely builds ref_gl.so and ref_vk.so side by side (real
dual-renderer engine), so batocera-system's auto-select for it needs
BR2_PACKAGE_HAS_LIBGL as well as BATOCERA_VULKAN/XORG7 - false on this
board (Panfrost only exposes GLES/EGL). A defconfig "is not set" line
in the board file can't override a forced Kconfig `select`, so this had
to be fixed at the actual select condition, confirmed via a failed build
("libgl is in the dependency chain of libglu... Stop.").
pcsx2's WXWIDGETS select turned out to be unrelated dead weight - its
.mk never references wx in any CMake option (OpenGL/Vulkan are already
properly gated on HAS_LIBGL/BATOCERA_VULKAN), so gated the select and
the .mk dependency on HAS_LIBGL too, matching how pcsx2 actually gates
its own optional GL support.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…d failure odroidm1/rk3568 wasn't in upstream's per-board platform/ARCH table, so it fell through to the generic default where the Makefile's own ARCH fallback (uname -m) picks up the build host's x86_64 arch instead of the cross-compile target, pulling in xbyak's x86-only cpuid.h unconditionally (confirmed via a real build failure: "-msse"/"-msse2" rejected by aarch64-buildroot-linux-gnu-g++ compiling gles2rice). Added an explicit branch mirroring RK3588/RK3576/H5 (WITH_DYNAREC=aarch64), reusing H5's CPUFLAGS (armv8-a+crc, cortex-a53 tuning) since it's a safe baseline subset for RK3568's Cortex-A55 cores with no extension-gated instructions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…ULKAN ppsspp.mk only flips ARM_NO_VULKAN=OFF (i.e. actually allows Vulkan) for RPi4/5; every other ARM board gets ARM_NO_VULKAN=ON regardless of the general -DVULKAN=ON flag, silently compiling Vulkan support back out. Confirmed via the built binary having zero Vulkan symbols despite BATOCERA_VULKAN=y. Added RK3568 to the same allowlist as RPi4/5. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
configgen-defaults-rk3568.yml still defaulted ps2 to libretro/play (a
stale upstream default from before PCSX2 was viable on aarch64) - our
board only registers the standalone pcsx2 emulator in es_systems.yml,
so this stale default made every PS2 launch try a nonexistent
libretro core and crash immediately ("Frontend is built for dynamic
libretro cores, but path is not set"). Confirmed live and fixed by
pointing the default at pcsx2/pcsx2 instead.
Separately, pcsx2-qt itself always defaulted to the xcb Qt platform
plugin, which aborts outright on this board (no X11, no compositor -
same failure class documented in duckstationGenerator.py for
duckstation-qt/melonDS). Reused the exact same WAYLAND_DISPLAY/DISPLAY
detection -> eglfs fallback pattern. Confirmed live: PCSX2 now reaches
its own BIOS-missing dialog instead of crashing at Qt init.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…pcsx2 dolphin-emu (standalone) always defaulted to the xcb Qt platform plugin, aborting outright on this board (no X11, no compositor). Confirmed live that eglfs actually works for Dolphin (unlike pcsx2-qt, which hits a separate "Failed to get window info from widget" Qt/eglfs multi-widget limitation) - Dolphin ran a real GPU-rendered session via libqeglfs-kms-integration.so + libgallium for 90+ seconds with no crash. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…for track C Board-file portion of B's "Enable PanVK + Vulkan-capable systems" (1246f47), re-applied manually with the PanVK/BATOCERA_VULKAN lines dropped - track C's Vulkan comes from the g29p1 blob + hand-written ICD, not a Mesa driver Kconfig select. flycastvl/ps2/play intentionally not re-added (already dead ends on B, see 04c0e46/5f1cf74e76). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
BR2_PACKAGE_BATOCERA_WAYLAND_LABWC=y: track C's blob Vulkan has no KMSDRM-direct display path (VK_KHR_display fails the same way under PanVK on B), so Wayland is back on the table after A/B dropped it. mali-g52-odroidm1.mk: the gbm_bo_get_fd_for_plane compat shim assumed the blob only ever exports the pre-standardization gbm_bo_get_fd_per_ plane name (true for g13p0) and unconditionally aliased the modern name to it based on grepping the vendor header text. g24p0's libmali.so.1.9.0 already exports gbm_bo_get_fd_for_plane directly - the header text just never caught up - so the alias pointed wlroots (the first real caller of this symbol on this board) at a symbol that no longer exists, breaking the link. Check the .so's actual exported symbols instead of trusting the header. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
Gate 1 (2026-08-12) confirmed g29p1 works against our unchanged vendor kbase (g25p0): GLES survives, vulkaninfo enumerates Mali-G52. Source moves from the "libmali" branch (g24p0) to "libmali-next" (g29p1 isn't published on the old branch), same JeffyCN mirrors repo, pinned commit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
pcsx2 pulls in libgtk3 unconditionally, and libgtk3's Wayland backend defaults to on once BR2_PACKAGE_WAYLAND is present (true now that labwc is back). g29p1 doesn't export wl_egl_window_create/resize/destroy - confirmed via nm -D, unlike eglGetPlatformDisplay/eglInitialize/ eglCreatePlatformWindowSurface which it does have - so the link fails. X11 stays available via BR2_PACKAGE_XORG7, this only drops GTK's Wayland-specific GDK backend. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
Root cause of the wl_egl_window_* link failures (kodi, then libgtk3's Wayland backend) wasn't a genuine gap in this board's Wayland-EGL support - it was mali-g52-odroidm1.mk's own EGL/GLES soname-aliasing loop overwriting a real, working libwayland-egl.so.1 that buildroot's plain "wayland" package already builds (confirmed via nm -D: wl_egl_ window_create/destroy/resize/get_attached_size all present, pure malloc/free bookkeeping with zero GPU dependency - this symbol set belongs to wayland.org's own reference implementation, not the GPU driver, unlike EGL/GLES/GBM which genuinely do need to come from the blob). Dropping wayland-egl from the alias loop lets wayland's real file stand, so this reverts the libgtk3-wayland-backend workaround from the previous commit - it was solving a problem we caused ourselves. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
Wayland_GLES_LoadLibrary() hardcoded platform=0, which skips the SDL_VIDEO_DRIVER_MALI dispatch batocera already added in SDL_egl.c (sdl2_add_video_mali_gles2.patch) and falls through to the legacy eglGetDisplay(native_display). The g29p1 proprietary blob does not support Wayland auto-detection on that legacy path and returns EGL_NO_DISPLAY, which surfaced as EmulationStation crash-looping with "Could not get EGL display" on every boot. Confirmed on real hardware: a raw ctypes EGL test using eglGetPlatformDisplayEXT(EGL_PLATFORM_WAYLAND_KHR, ...) succeeds, while replicating the exact legacy eglGetDisplay(wl_display) call SDL was making fails with EGL_NO_DISPLAY. Passing EGL_PLATFORM_WAYLAND_KHR unconditionally (not gated behind SDL_VIDEO_DRIVER_MALI) is safe for Mesa too, since EGL_KHR_platform_wayland is a standard extension. Batocera's existing Mali patch only wired up kmsdrm (EGL_PLATFORM_GBM_MESA); nothing had previously combined the Mali blob with Wayland, so this gap was never hit before track C.
writeHotKeyConfig() only ever wrote input_enable_hotkey_btn (arming the hotkey modifier), never any joypad action bound to it - cleanControllerConfig even actively disable_all()s input_exit_emulator* every game launch via prefix match. Only the keyboard input_exit_emulator="escape" default actually quit a running libretro core; Hotkey+Start (batocera's own force-quit convention, see es_input.cfg's keyboard hotkey=select binding) did nothing on a gamepad. Confirmed live on ODROID-M1 (SHAKS S6b pad, FBNeo Korean core/Night Slashers): Select+Start did not exit until input_exit_emulator_btn was set to Start's button id. This is shared configgen code, not board- or GPU-track-specific - the gap should be identical on A/B, just never exercised there.
…ns too This board's Vulkan driver comes from the g29p1 blob (hand-written mali.json ICD), not a Kconfig-selectable Mesa driver, so it was deliberately left off - but that missed that the option also registers PPSSPP's gfxbackend.ppsspp.emulator.yml (the Vulkan choice in ES's own PSP graphics-API menu never appeared without it) and selects VKQUAKE/VKQUAKE2/VKQUAKE3/QT6BASE_VULKAN. Confirmed safe: every Mesa Vulkan driver select this option pulls in is itself gated behind other targets (X86/RPi/PANFROST_MESA3D/ FREEDRENO_MESA3D) that don't match rk3568/bsp-odroidm1, so enabling it here only adds the generic vulkan-tools/spirv-tools/shaderc packages plus the Vulkan-native ports/UI options above - no conflicting driver.
…only Vulkan to Wayland surfaces Confirmed live via vulkaninfo's Instance Extensions list: the g29p1 blob's Vulkan ICD only implements VK_KHR_display (bare DRM, no compositor) among windowing-system surface extensions - no VK_KHR_wayland_surface at all. Without this, every Vulkan app's own surface/device creation for a Wayland window fails outright even though vulkaninfo enumerates the GPU fine (confirmed live: PPSSPP's SDL2 window creation succeeded once SDL2 itself got Vulkan support enabled via the sdl2.mk buildroot-submodule fix, but PPSSPP's own Vulkan backend init then failed and silently fell back to GLES). New package mirrors ROCKNIX's own fix for the same blob/board family (RK3566/g29p1, projects/ROCKNIX/packages/graphics/vulkan-wsi-layer/ package.mk) - ARM's open-source vulkan-wsi-layer implements VK_KHR_wayland_surface as a Vulkan layer on top of the bare ICD. Deviates from ROCKNIX's recipe in two places, both confirmed live: - WSIALLOC_MEMORY_HEAP_NAME=system, not their "linux,cma" - this BSP 6.1 kernel's /dev/dma_heap/ only has reserved/system/system-uncached, no heap named "linux,cma" (different DMA-heap exporter/naming than whatever ROCKNIX's own kernel registers under that name). - Layer .so and .json manifest installed to the SAME directory (/usr/share/vulkan/implicit_layer.d/), not split across /usr/lib + implicit_layer.d like ROCKNIX's package.mk - the manifest's "library_path" is the relative "./libVkLayer_window_system_integration.so", which the Khronos loader resolves against the directory containing the *manifest*, not against /usr/lib. Left unverified whether ROCKNIX's split actually works for them; co-locating is unambiguously correct per the loader's documented resolution rule. Requires BR2_PACKAGE_BATOCERA_VULKAN=y - previously left off (see the .board comment above this select) on the correct-as-far-as-it-went reasoning that this board has no Kconfig-selectable Mesa Vulkan driver, but that option also gates PPSSPP's gfxbackend.ppsspp.emulator.yml (the Vulkan choice in ES's own PSP graphics-API menu never appeared without it) and, as of this commit, this layer. Status: builds and installs cleanly, loads and gets dispatched to (vkCreateWaylandSurfaceKHR is called - confirmed via vulkaninfo, this extension wasn't even recognized before the layer existed). Currently blocked on a live, unresolved failure: the call returns VK_ERROR_OUT_OF_HOST_MEMORY while enumerating labwc's zwp_linux_dmabuf_v1 format/modifier list (wsi/wayland/surface.cpp's get_supported_formats_and_modifiers(), custom_allocator-backed util::vector filling from the dmabuf format/modifier event listener - this board's Mali AFBC modifier list is very large, hundreds of format+modifier pairs per `wayland-info`, prime suspect but unconfirmed without a debugger). VULKAN_WSI_DEBUG_LEVEL=5 produces no extra output; MangoHud layer interaction ruled out (DISABLE_MANGOHUD=1, same failure). See project Joplin note for the full investigation writeup.
…mitted upstream) Points at a detached-HEAD commit (d851f79697) on top of the existing buildroot fork pin (95d26b3e3f) - not yet pushed anywhere, since this worktree's buildroot submodule only has the batocera-linux/buildroot upstream remote configured, no personal fork. The fix itself: package/ sdl2/sdl2.mk no longer requires a Mesa Vulkan driver to enable --enable-video-vulkan (see that commit's own message). Needs a real fork remote added and pushed before this is reproducible from a fresh clone.
…ilure Corrects a0ad43e's misdiagnosis. That commit's Status note blamed VK_ERROR_OUT_OF_HOST_MEMORY on the dmabuf modifier-list vector (custom_allocator OOM in get_supported_formats_and_modifiers) - that's wrong. The real failure happens earlier and never reaches that code: wsi/wayland/surface.cpp's surface::init() hard-requires the zwp_linux_explicit_synchronization_v1 Wayland global, which wlroots (labwc's compositor) has never implemented - it went straight to the newer linux-drm-syncobj-v1 model instead. Every failure branch inside surface::init() (missing dmabuf/explicit_sync/presentation interface, roundtrip failure, real OOM) gets collapsed into the same generic VK_ERROR_OUT_OF_HOST_MEMORY by CreateWaylandSurfaceKHR's caller (surface_properties.cpp), which is what made the error code so misleading. Confirmed live: `wayland-info | grep -i explicit` on this device returns nothing, and (once logging was actually working, see below) WSI_LOG_ERROR at the exact explicit_sync check fired every time. Also root-caused why VULKAN_WSI_DEBUG_LEVEL was a silent no-op the entire time this was being investigated: util/log.hpp gates wsi_log_enable behind `#ifdef NDEBUG`, and buildroot's cmake-package infra defaults new packages to CMAKE_BUILD_TYPE=Release (-DNDEBUG) - so every WSI_LOG_ERROR call across the whole layer was compiled out to nothing, regardless of the env var. No gdb or extra tooling was needed once this was found - just build Debug. Fix: apply ROCKNIX's own sync.patch for this exact pinned layer commit (8f077c5, matches VULKAN_WSI_LAYER_VERSION here) - authored by Ivan Podogov (ginkage), who wrote the layer's Wayland backend upstream and ships this same patch to run it on wlroots (sway) compositors. Makes explicit sync optional with an implicit dma-buf-fence fallback (CPU-side wait_payload when no acquire-fence interface is available), forces FIFO present mode (implicit sync isn't safe with MAILBOX/IMMEDIATE), remaps ARGB8888/ABGR8888 to the opaque XRGB8888/XBGR8888 fourccs compositors advertise more reliably, adds VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, and disables the ABGR2101010 format table entry. Saved verbatim as 0001-fall-back-to-implicit-sync.patch for buildroot's automatic per-package patch application; explicitly NOT applying ROCKNIX's sibling vklayer-driver-path.patch (bare-soname library_path) since that would break this package's current co-located implicit_layer.d install layout. Also, independently of the above (found live, not covered by the ROCKNIX patch): the manifest's relative "./libVkLayer_..." library_path failed to dlopen for at least one real launch context (PPSSPP via SSH, different CWD) even though it worked for vulkaninfo - switched mali.json's sibling manifest... n/a here, but noting for the record: this package's own install step already co-locates the .so and .json, matching what turned out to be necessary. DMA heap: switched WSIALLOC_MEMORY_HEAP_NAME from "system" to "system-uncached", per ginkage's own README recommendation for this allocator backend - "system" is a cached page-allocator heap (not CMA/contiguous, correcting an earlier version of this comment), and a cached heap risks coherency artefacts on buffers shared between GPU and compositor. CMAKE_BUILD_TYPE=Debug added temporarily for bring-up so WSI_LOG_ERROR/WARNING actually print - remove once the Vulkan surface/swapchain path is confirmed stable end-to-end (revert to buildroot's Release default). Verified live end-to-end: vkCreateWaylandSurfaceKHR and vkCreateSwapchainKHR both succeed (previously OUT_OF_HOST_MEMORY / INITIALIZATION_FAILED), PPSSPP with GraphicsBackend=VULKAN runs a 20s+ session with no fallback to GL, no dmesg GPU faults, and multiple real Vulkan pipelines compiled+cached (ShaderManagerVulkan/ PipelineManagerVulkan save messages). This is Track C's first actual Vulkan-rendered frame. Credit: root-caused independently in this session via direct source reading (explicit_sync requirement + NDEBUG logging gate) and cross-checked against an equivalent independent analysis from another session, which additionally identified ROCKNIX's existing sync.patch as the vetted fix and system-uncached as the correct heap - both adopted here instead of a hand-rolled equivalent. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…Vulkan cores This Mali blob ICD rejects vkCreateDevice outright with VK_ERROR_INITIALIZATION_FAILED (rather than tolerating it, as more lenient drivers do) for two spec violations the layer could itself introduce or pass through unmodified. Found by tracing why libretro ppsspp_libretro.so (RetroArch) crashed with SIGABRT under Vulkan even though standalone PPSSPP (SDL2) already worked cleanly after the sync.patch fix - the device-creation path is entirely different between the two (RetroArch's own Vulkan HW render context negotiation vs. PPSSPP's own SDL2-based Vulkan init), so this is a genuinely separate bug from the explicit_sync one, discovered only once RetroArch's own VkResult (-3, VK_ERROR_INITIALIZATION_FAILED) was logged directly, since the core itself swallows the failure silently and proceeds to call vkGetDeviceQueue on the resulting invalid device handle, which is what the Khronos loader's validation actually catches and aborts on. 1. add_device_extensions_required_by_layer() could append an extension the application already requested itself - confirmed live: RetroArch's negotiation already requests VK_KHR_external_fence/_fd, which this function's own "optional extensions independent of winsys" list and its per-platform required-extensions list both also add unconditionally, producing a genuine duplicate extension name in ppEnabledExtensionNames (forbidden by VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-01387). Fixed by skipping anything extensions_to_enable already contains in both places. 2. RetroArch's own VkDeviceCreateInfo sets a legacy non-NULL pEnabledFeatures *and* chains a VkPhysicalDeviceFeatures2 in pNext at the same time (forbidden by VUID-VkDeviceCreateInfo-pNext-00373). The layer forwards the app's struct essentially unmodified, so this passed straight through. Fixed in create_device() by clearing pEnabledFeatures whenever a VkPhysicalDeviceFeatures2 is also present in pNext - the pNext version is a strict superset of what the legacy struct expresses, so dropping the redundant pointer is always safe. Saved as 0002-fix-device-create-info-spec-violations.patch (verified applying cleanly with `patch -p1 --dry-run` against a pristine checkout of the pinned commit 8f077c5, independent of 0001's hunks - touches different files). Verified live end-to-end: libretro ppsspp_libretro.so with video_driver=vulkan went from immediate SIGABRT to a full clean run - device created, Vulkan surface + 3-image swapchain created, FIFO present mode selected, no dmesg GPU faults, 10s+ sustained. This is a generic fix in the layer's own device-creation path, independent of windowing system, so it should also benefit any other libretro core using RetroArch's Vulkan HW render negotiation (parallel_n64/ParaLLEl-RDP, MAME with Vulkan support, etc.), not just PPSSPP. Note: standalone Dolphin (dolphin-emu, Qt6) remains separately broken under Track C - it fails even earlier, before any Vulkan/WSI call is ever reached, most likely in Qt's own native wl_surface handle acquisition under labwc (`-platform wayland` gets a real window on screen but "Failed to initialize video backend!"; `QT_QPA_PLATFORM` env var is inexplicably ignored in favour of `-platform` CLI arg, a still-unexplained Qt6 quirk on this build worth revisiting). Not attempted further this session - out of scope of this patch, which is specifically about the vkCreateDevice failures above. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
Was building without -DENABLE_VULKAN at all - confirmed live via the libretro dolphin_libretro.so core's own maps (only libmali.so loaded, no libvulkan.so, "context type: gl" in the RetroArch log) that this core has never actually attempted Vulkan on this board, GLES-only. ROCKNIX's dolphin-lr package.mk enables Vulkan unconditionally whenever VULKAN_SUPPORT=yes (no ARM/x86 device gating, unlike their parallel-n64-lr which is x86_64-only for HAVE_PARALLEL - see next commit's investigation) - this core's Vulkan backend is a real, generically-available option upstream, not an x86-only experimental one. Matches the same BR2_PACKAGE_BATOCERA_VULKAN gate the standalone dolphin-emu package already uses. Not yet rebuilt/verified live - queued for the next full image build alongside the standalone dolphin-emu Vulkan fix (which was stale-built before BATOCERA_VULKAN was turned on) and PCSX2/vkquake (already BR2_PACKAGE_*=y in .config/.board but never actually built into the image that's currently flashed on the device). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…th BATOCERA_VULKAN=y duckstation.mk's BR2_PACKAGE_BATOCERA_VULKAN branch adds a real BR2_PACKAGE_MESA3D (not mesa3d-headers) dependency, but duckstation's own Config.in never selects/depends-on it - buildroot's own legality check fails the whole board build the instant BATOCERA_VULKAN=y (confirmed live: "mesa3d is in the dependency chain of duckstation that has added it to its _DEPENDENCIES variable without selecting it or depending on it from Config.in"). This branch was presumably always dead code on this board until now, since nothing had turned BATOCERA_VULKAN on before. Not worth chasing further: duckstation-qt was already abandoned on A/B for a separate, unrelated reason (Qt/eglfs can't host its multi-widget window structure without a compositor - "Failed to get window info from widget", see project memory), and PSX is already covered by libretro swanstation (the actual recommended core, 58fps+ software-rendered, no GPU faults). A real BR2_PACKAGE_MESA3D dependency would also risk the same class of Kconfig conflict this board already hit once with Saturn kronos (this board only configures BR2_PACKAGE_MESA3D_HEADERS for the blob, not full mesa3d). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…tocera-system's select Previous commit's "# BR2_PACKAGE_DUCKSTATION is not set" line in the board defconfig had no effect: batocera-system/Config.in unconditionally selects DUCKSTATION for GLES3 boards, and Kconfig select always wins over a plain defconfig negation - confirmed live, .config still showed BR2_PACKAGE_DUCKSTATION=y after regenerating and the build hit the identical mesa3d error again. Fixed at the actual mechanism: added a depends-on guard directly to duckstation/Config.in itself. Kconfig silently drops a select whose target's own depends-on evaluates false (same non-fatal WARNING class already seen for the pre-existing GStreamer OpenGL dependency warnings in this board's build log) - this is the standard way to locally override a select from shared/upstream Config.in without touching that shared file. Condition matches the real conflict: BR2_PACKAGE_MESA3D_HEADERS (this board's vendor-blob setup) together with BR2_PACKAGE_BATOCERA_VULKAN (which makes duckstation.mk pull in full BR2_PACKAGE_MESA3D). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…ndition The depends-on guard from the previous commit didn't work: Kconfig's select overrides a target's own failed depends-on with only a WARNING (same class as this build's pre-existing, harmless GStreamer OpenGL dependency warnings) - confirmed live, .config still showed BR2_PACKAGE_DUCKSTATION=y after regenerating, and the build hit the identical class of error again for a second dependency (cpuinfo, after mesa3d), since the package was never actually disabled. Real fix: add the exclusion condition directly to batocera-system/Config.in's own select line, following the exact same pattern already used there for other board-specific exclusions (!BR2_PACKAGE_BATOCERA_TARGET_RK3326, !..._S9GEN4). Can't key off this board's own BR2_PACKAGE_BATOCERA_TARGET_RK3568 flag since that's shared across all three A/B/C GPU-driver tracks on this same physical board - only Track C has BR2_PACKAGE_BATOCERA_VULKAN on, so gating on BR2_PACKAGE_MESA3D_HEADERS && BR2_PACKAGE_BATOCERA_VULKAN together is both the precise real conflict condition and inert on A/B. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
Comments interleaved inside the backslash-continued DUCKSTATION select if-expression broke the Kconfig parser (it treated the comment as ending the statement early, then choked on the leftover !(...) as a bogus new statement). Move the explanatory comment above the select line instead; the exclusion condition itself is unchanged.
SDL3_DEPENDENCIES unconditionally added mesa3d whenever BATOCERA_VULKAN=y, even though SDL's Vulkan support only actually needs vulkan-loader/vulkan-headers. On vendor-blob boards using mesa3d-headers instead of full mesa3d (ODROID-M1 Track C), this tripped buildroot's package-legality check (mesa3d symbol not =y) since mesa3d-headers and mesa3d are mutually exclusive - same class of conflict as the earlier duckstation fix.
Was showing upstream's plain "44-dev-<hash> <date>" (e.g. "44-dev- 8920c48 2026/08/26 15:22"), which visually clashes with our own git release tag convention (batocera44-odroidm1-vX.Y.Z, already decided). Now: on an exact release tag, batocera.version shows that tag verbatim (e.g. "batocera44-odroidm1-v1.0.0"); otherwise falls back to "batocera44-odroidm1-dev-<hash>" (still contains "dev" so the existing BATOCERA_SYSTEM_COMMIT logic keeps appending the hash). Board-gated via BR2_PACKAGE_BATOCERA_TARGET_BSP_ODROIDM1 since batocera-system.mk is shared across all boards - other boards keep upstream's default. Doesn't change how update detection actually works: do_upgradecheck_0 does a raw string comparison between the local batocera.version content and the remote manifest (still not published - deferred to first release), so it's unaffected either way by this text-format change. Known minor side effect: board/batocera/scripts/post-image-script.sh's SUFFIXVERSION extraction (`^\([0-9\.]*\)`) expects the version to start with digits, so our new "batocera44-..." string yields an empty SUFFIXVERSION and a double-dash in buildroot's raw output filename (batocera-rk3568-bsp-odroidm1--20260826.img.gz). Harmless for us - our own archiving step always renames to batocera-rk3568-bsp-odroidm1- g29p1-vN.img.gz regardless - so not fixing the shared script for this cosmetic-only case. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
Follow-up to d05f5c6. User feedback: before we actually cut a tagged release, keep batocera.version identical to upstream's own dev-build identifier ("44-dev-<hash> <date>") rather than rebranding every untagged build as "batocera44-odroidm1-dev-<hash>". The missing commit hash that started this whole investigation was purely the git-worktree docker mount bug (fixed in 520d806) - upstream's format was never broken, our build environment just couldn't populate it. Our own release-tag format (batocera44-odroidm1-vX.Y.Z) still kicks in correctly once HEAD is exactly on one of those tags - that part is unchanged, since that's a genuine, deliberate identifier for an actual release, not a rebrand of ordinary dev builds. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
Live-verified auto core/API selection against the benchmarked table (project_odroid_retro.md) game-by-game. Genesis/FBNeo/Saturn/PSX all matched. N64 didn't: it launched glide64mk2 instead of rice. Root cause: ES's "auto" choice isn't determined by es_systems.yml's core listing order - it's computed by comparing each (emulator, core) pair against this board's configgen-defaults emulator/core keys (see python-src/batocera-es-system's registry.py, get_systems_metadata). The earlier "auto order" fix (mentioned in project_odroid_retro.md) reordered es_systems.yml's n64 core list, which has zero effect on that comparison - the actual default (mupen64plus + glide64mk2) was never overridden here, so it fell through to the shared configgen-defaults.yml value the whole time. Auditing the same mechanism for the other benchmarked standalone-emulator systems found two more real mismatches (not yet live-tested, but the same class of bug, confirmed via source inspection): - gamecube/wii: emulator was "libretro" (copied verbatim from the shared configgen-defaults-rk3568.yml), which picks libretro-dolphin - not the standalone dolphin (emulator: dolphin) this board actually benchmarks and needs for the Wayland-only OpenGL fix. dolphinGenerator.py already defaults to Vulkan unless gfxbackend=OGL is set, so no extra option needed for the API side. - dreamcast: no override at all, falling through to the shared file's libretro-flycast default instead of standalone flycast. Also added flycast_renderer=4 (forces Vulkan) since flycastGenerator.py's own default is OpenGL, unlike dolphin/ppsspp which already default to Vulkan. psp needed no change: ppssppConfig.py already defaults to "3 (VULKAN)" when gfxbackend is unset, matching the benchmark recommendation as-is. Not yet live-verified on hardware (n64 was; gamecube/wii/dreamcast weren't reached yet in the ongoing verification pass) - flagged in project_odroid_retro.md for the next round of testing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
Continuation of the auto core/API verification pass (n64/gamecube/wii/ dreamcast fixed earlier). PS2's auto default was set to pcsx2, which is the core we already determined is structurally broken on this board's Mali blob (DATA_INVALID_FAULT GPU faults - see project_odroid_retro.md's "Mali G52 blob 구조적 한계" section). Confirmed live: auto silently launched pcsx2, dmesg showed "GPU fault 0x5b from job slot 0", and the game visibly hung. Switched the default to aethersx2 (the actually-recommended, working choice). pcsx2 stays installed/selectable in ES as a fallback, just no longer the silent default that most users would hit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…doring Follow-up to 4dc8fe5 (PS2 auto default fix). Live-testing that fix surfaced a real launch failure: "libXrandr.so.2: cannot open shared object file" - a leftover gap from AetherSX2's prebuilt-binary NEEDED list that nothing had exercised before, since PS2's auto default had been silently pointing at pcsx2 this whole time. Initially vendored libXrandr.so.2 + its libXext/libXrender/libX11 transitive closure from Debian arm64 packages (same technique already used for the GL/GLX/curl/openssl shims in aethersx2/libs/), but per feedback: unlike those, there's no ABI/missing-feature reason libX11's family can't just be built normally via buildroot's own xlib_libX11/ libXext/libXrender/libXrandr packages - so build them for real instead. Reverted the vendored copies, added a select chain to aethersx2's Config.in instead (same flattening pattern as melonds/Config.in - these xlib_* Config.in entries all live inside "if BR2_PACKAGE_XORG7", so a select landing on one of them doesn't reliably cascade to that symbol's own further selects). Confirmed live: libXrandr/libXext/libXrender/libX11 all built successfully via buildroot and installed into the standard /usr/lib, which aethersx2Generator.py's LD_LIBRARY_PATH already covers - no changes needed there. No performance impact: aethersx2Generator.py forces QT_QPA_PLATFORM= wayland, so the Qt xcb platform plugin path that actually pulls libXrandr in at runtime (display mode/refresh-rate queries) is never taken - same "NEEDED-pass only" story as the GL/GLX shims that already exist in aethersx2/libs/. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
Convenience fix requested during VU8M setup testing: enabling VU8M (overlays=display_vu8m) already requires editing config.ini, which is the one file on the PC-visible FAT32 boot partition. batocera.conf (the "correct" place for display.rotate) lives on the userdata partition (ext4, not readable from a plain Windows/Mac file browser), and batocera-boot.conf - while technically fine to hand-edit here (nothing regenerates it wholesale; batocera-config only ever amends specific keys like sharedevice/rootshadowpassword via targeted sed, never display.rotate) - is a second file to open for no real reason when config.ini is sitting right there. config.ini is checked first, ahead of the existing batocera-boot.conf path, so setting VU8M up (enable + rotate) is now a single-file edit. Verified live: "Rotation from config.ini: [1]" logged, correct 800x1280 crop and -o 1 fbv rotation applied. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…rd README batocera-backglass-window.cpp's font candidate lists (both header and description) only ever contained DejaVu Sans / Liberation Sans - both Latin-only, so any Korean text (game titles, backglass metadata) rendered as missing-glyph boxes on the VU8M backglass screen. This is a narrow gap in an otherwise Korean-font-aware system: ES itself already ships a bundled Korean fallback font (PyeojinGothic-Medium, compiled into the ES binary as a resource), and this board already has Noto Sans KR + NanumGothic installed as real font files (via the vanilla upstream nanum-font package, unrelated to our fork) - backglass's own hardcoded candidate lists just never got updated to include either. Prepended NotoSansKR-VF.ttf (checked first) to both candidate lists - it's a variable font with full Latin+CJK coverage in one file, so one font renders both scripts consistently (SDL_ttf can't font-switch mid-string anyway). Falls back to the existing DejaVu/Liberation chain if Noto isn't present. Compiled and deployed live; full visual confirmation still pending (testing got sidetracked investigating an unrelated HDMI+VU8M simultaneous-connection issue - see below). Also adds README-odroidm1.md: repo-root, Korean, covers what's added over vanilla Batocera, VU8M/HDMI display setup (including the config.ini single-file rotation trick from the commit below), and the full per-system performance/auto-core table. Iterated heavily with the user this session - still being refined, not final. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4zVPhdz6gmjHPNpGGTQei
…anism Live testing on-device found that S65values4boot already syncs display.rotate/display.rotate.<connector> from batocera.conf into batocera-boot.conf on every shutdown/reboot (vanilla mechanism) - the config.ini duplication added in 58fcc13 was unnecessary, since the boot splash's existing batocera-boot.conf fallback already picks up the correct value with no extra config needed. Also fixes the real bug behind this session's dual-display report: VU8M rotation is controlled by global.videooutput2/display.rotate2.<connector> in batocera.conf (set via the ES MULTISCREENS menu, or directly with batocera-settings-set), not by anything in batocera-boot.conf or config.ini - those only ever affect the primary output. Verified live: global.videooutput2=DSI-1 + display.rotate2.DSI-1=3 (270 degrees) gives correct portrait orientation on VU8M. README updated to describe the actual mechanism instead of the config.ini workaround.
…README 270 degrees was this particular panel's measured correct orientation, not a general fact about VU8M - actual mounting can vary per unit.
- Remove the standalone "boot partition file editing" section - stale instructions, redundant with each subsection already saying where its own file lives. - Shrink the HDMI+VU8M "not recommended together" caveat down to the one hardware fact that's still true (DSI has no hotplug detection) - today's live testing showed no actual splash-rotation problem once global.videooutput2 is set correctly, so the earlier elaborate warning overstated a non-issue. - Rename "화면 회전" to "화면 회전값 설정" and drop the global.videooutput2 example from it (that's the previous section's concern, not rotation) - keep only rotation-specific keys/commands here.
…ass/rotation section
- Move the SHARE-partition-init caveat to the top of the section (it's a precondition for everything below, not an afterthought). - Split the reboot out of the settings command block with a one-line explanation: EmulationStation only reads/applies videooutput2 and rotation at its own startup, so a plain batocera-settings-set has no effect until the next boot.
Both the primary and backglass screens have an option literally labeled "SCREEN ROTATION", which is confusing without their full menu paths (confirmed against GuiMenu.cpp): SYSTEM SETTINGS > HARDWARE for the main screen, vs. SYSTEM SETTINGS > HARDWARE > MULTISCREENS > BACKGLASS / INFORMATION SCREEN for VU8M.
Same upstream snapshot merged into the C track (odroid-m1-g29p1, commit cbeaa11) on 2026-08-17, applied here to odroid-m1-bsp-kernel so PR #4's diff reflects genuine A-vs-C track differences instead of upstream drift. Merged with --allow-unrelated-histories (upstream's 2026-08-04 history squash has no shared ancestor with this fork). 243 conflicted files. 228 were files this branch never customized - resolved by taking origin's version wholesale (git checkout --theirs). The other 14 (this board's own S02resize/audio-config/power-mode/ Ssplash-mpv/es_input.cfg/emulationstation-standalone/storage-manager/ melonDS/libretro-core-info/libretro-kronos/batocera.conf fixes) were reconciled via git merge-file: base = the file's content immediately before this branch's own customizing commit, ours = this branch's current version, theirs = origin's new version - applies this branch's own diff cleanly on top of upstream's latest instead of blindly preferring either side. All 14 merged with zero remaining conflict markers except melonds.mk, whose 2 conflicting hunks (X11/libinput dependency gate, ENABLE_WAYLAND rationale comment) are pure odroid-m1 board-specific additions absent from both base and origin - resolved by keeping this branch's version. buildroot submodule conflict resolved by keeping this branch's own pin (fork/odroidm1-mpv-gbm-fix) - already only 1 trivial, unrelated commit (webkitgtk build fix) behind origin/master, unlike C's buildroot fork which needed real reconciliation. Also fixed 6 files that lost their executable bit during manual reconciliation (git show | cp does not preserve file mode).
…the ES version string ES's version label is literally "BATOCERA.LINUX ES V" + BATOCERA_SYSTEM_VERSION, so using the git tag (batocera44-odroidm1-vX.Y.Z) verbatim doubled up into "...ES Vbatocera44-odroidm1-v1.0.0". Strip the tag down to "44-odroidm1-X.Y.Z" for the version string while keeping the tag itself unchanged (still reads well in GitHub's release list) - final ES label becomes "BATOCERA.LINUX ES V44-odroidm1-1.0.0 <build date>", matching the shape of upstream's own "V44-dev-<hash>".
…s ambiguous merge-base Both odroid-m1-bsp-kernel and odroid-m1-g29p1 independently merged the same upstream squash commit (e38b00f) with --allow-unrelated-histories, which left git (and GitHub's PR diff) with two candidate merge-bases and no single common ancestor - PR #4's diff stayed at ~390-540 files instead of shrinking to the genuine A-vs-C track difference. This merge changes no C-track content (tree is identical to the previous commit) - it only records odroid-m1-bsp-kernel's current tip as an ancestor of this branch, giving the two branches one unambiguous shared commit going forward so PR #4's diff resolves to the real difference.
Pyohwan
left a comment
There was a problem hiding this comment.
AI 4차 리뷰 — 릴리스 전 점검 (참고용)
읽은 범위: 로컬 clone에서 8920c482..edb018a887 41개 커밋과 그 diff 전량, git diff origin/odroid-m1-bsp-kernel HEAD 120파일 전수, A안 리뷰 대응 9종의 C안 생존 여부 스팟체크, fsoverlay 사본 4종을 공용 원본과 직접 diff, CI 로그(run 33238810717), ruff format의 py313/py314 동작 최소 재현.
| 형식 | 코드 품질 | 컨벤션 | 테스트/CI | 릴리스 정합 |
|---|---|---|---|---|
| ✅ | ✅ | ❌ (lint fail) | ❌ |
판정: 지금 상태로는 승인하기 어렵습니다. 릴리스 이미지에 직접 영향이 가는 3건이 열려 있습니다 — 라인 인라인 5건(❌ 4 /
라인에 붙지 않는 내용만 아래에 남깁니다.
1. -s ours 머지 — 목적은 달성했습니다
edb018a887의 의도(두 개의 merge-base로 PR diff가 부풀던 문제 해소)는 실제로 확인했습니다.
- 트리 변경 없음:
git diff edb018a887^1 edb018a887→ 빈 출력 - PR diff가 540 → 120파일로 수렴, 로컬
git diff origin/odroid-m1-bsp-kernel HEAD(120파일, +10816/-486)와 일치
부작용은 A안 tip이 이 브랜치의 조상으로 기록돼, 앞으로 A안에 들어가는 수정이 C안으로 자동 유입되지 않는다는 점입니다. 현재는 문제가 없습니다 — 1~3차 리뷰 대응 9종이 C안에 전부 살아 있는 것을 확인했습니다(BSP_ODROIDM1 게이팅 · storage-manager 파티션 ignore fallback · configgen defaults 분리 · gallium_hud_fallback opt-in · syslinux 동기화 · dosbox 중복 플래그 제거 · exit_emulator nest · mali GBM feature select · patches-source.txt).
다만 이제 두 트랙이 같은 수정을 두 벌로 유지하는 구조입니다(A안=공용 파일 직접 수정, C안=board fsoverlay 사본). 어느 쪽이 정본인지, 새 수정이 생기면 어디에 넣고 어떻게 반대편으로 옮길지를 README-odroidm1.md나 .board 주석에 한 줄 적어두시면 좋겠습니다.
2. CI가 A안은 통과하는데 C안만 실패합니다
| PR | lint | unit-tests |
|---|---|---|
| #1 (A안) | ✅ pass | ✅ pass |
| #4 (C안) | ❌ fail | ✅ pass |
원인 두 갈래는 각각 overlay.py:125, aethersx2Generator.py:21 인라인에 남겼습니다. 둘 다 국소 수정이고, 현재 릴리스 태그(batocera44-odroidm1-v1.0.0)가 붙은 커밋이 바로 이 실패 상태라는 점만 짚어둡니다.
3. 잘된 것
- 공용 파일 수정을 board fsoverlay로 전환한 것이 1~3차 지적의 근본 해결입니다. 게다가 사본이 upstream 최신 + 보드 수정으로 정확히 맞아떨어집니다(원본 대비 각 16·35·28·15줄 = A안이 공용 파일에 넣었던 수정분과 동일). 현 시점 drift 0.
- AetherSX2
libXrandr를 벤더링 대신 buildroot 정식 패키지로 전환(acc831e29a) — 1차 벤더링 지적의 정석 해결입니다.libs/에 남은 GL/GLX/curl/openssl은 ABI 사유가 문서화돼 있어 이견 없습니다. - auto 코어 기본값을 실측 기준으로 재정렬하면서, **"auto는
es_systems.yml나열 순서가 아니라 defaults yml의 emulator/core 쌍이 결정한다"**는 근본 원인까지 규명한 부분. 증상만 고치고 넘어가기 쉬운 지점이었습니다. - 릴리스 버전 체계: 태그가 HEAD에 이미 붙어
git describe --exact-match가 동작하고, ES 라벨이V+batocera...-v1.0.0으로 겹치는 것을 sed로 막은 것도 맞습니다.
4. 승인 조건
인라인 ❌ 4건 중 아래 3건이 릴리스 이미지 내용물을 바꿉니다.
fbneo_koreaninfo 심링크 (README가 대표 기능으로 소개하는 항목)batocera-upgradefsoverlay 사본 제거 (또는 공용 파일 수정 원복 — 둘 중 하나)- CI lint 2건
이 3건이 정리되면 승인 의견을 내겠습니다. python3.14 경로 건은 릴리스를 막지 않는 후속 항목입니다.
5. AI 한계 — 사람 확인 필요
실기 부팅·성능·Vulkan 동작·AetherSX2 안정성, 그리고 실제 이미지를 구워 /usr/share/libretro/info/와 /usr/bin/batocera-upgrade의 최종 내용물을 확인하는 것은 정적 분석 범위 밖입니다. 위 지적은 모두 코드·설정 텍스트 대조와 CI 로그, ruff 동작 재현에 근거합니다.
🤖 Reviewed by Claude Opus 5 (1M context)
|
|
||
| # Main entry of the module | ||
| # Configure fba and return a command | ||
| def generate(self, system, rom, playersControllers, metadata, guns, wheels, gameResolution): |
There was a problem hiding this comment.
경로에 파이썬 버전이 박혀 있습니다. 현재는 맞습니다 — buildroot/package/python3/python3.mk의 PYTHON3_VERSION_MAJOR = 3.14와 일치합니다.
다만 buildroot가 3.15로 올라가면 이 오버레이는 에러 없이 그냥 쓰이지 않는 파일이 됩니다. rootfs에 /usr/lib/python3.14/...가 하나 더 생길 뿐이고 configgen은 새 경로에서 원본을 그대로 씁니다. 같은 fsoverlay 방식이라도 /usr/bin/* 쪽은 경로가 고정이라 이런 실패가 없는데, 이 두 개(duckstationGenerator.py·flycastGenerator.py)만 조용히 무효화되는 구조입니다.
릴리스를 막을 사안은 아니고, 다음 buildroot 범프 때 확인할 항목으로 남겨두시면 되겠습니다. (
- Add the missing fbneo_korean_libretro.info symlink (present in the A track, missing here) - fbneo_korean is the default FBNeo core on this board and README-odroidm1.md advertises it, but without this symlink RetroArch can't read the core's name/extensions/options metadata. - Remove the board fsoverlay copy of batocera-upgrade - confirmed byte-identical to the shared package/batocera/core/batocera-scripts copy (the local-var/$? fix already landed in both), so the fsoverlay copy does nothing now except silently re-shadow the shared file on the next upstream sync. - Revert the erroneous "except ValueError, ImportError: is Python 2 syntax" fix from 52523fc - it's valid PEP 758 syntax (unparenthesized multi-exception except clauses), accepted starting Python 3.14, which this build already targets (pyproject.toml target-version = "py314", buildroot PYTHON3_VERSION 3.14.5). Confirmed via `ruff format --target-version py314`, which actively strips the parentheses back out - the original upstream code was correct. - Remove aethersx2Generator.py's unused imports (Mapping, SystemConfig, Guns, Input, DeviceInfoMapping, Resolution) - the 6 ruff-check failures that were breaking CI on this branch only, since this file never ran through CI before (per 1st/2nd review rounds). Auto-fixed with `ruff check --fix`. All four verified with a local ruff 0.16.5 install (check + format --diff), matching this repo's pyproject.toml configuration.
Pyohwan
left a comment
There was a problem hiding this comment.
AI 5차 확인 — 4차 블로킹 항목 해소, 승인 의견
fdc833a83b(4파일, +7/-547) 검증 결과입니다. 4차에서 "정리되면 승인 의견을 내겠다"고 남긴 3건이 모두 해소됐습니다.
| 4차 지적 | 결과 | 확인 방법 |
|---|---|---|
fbneo_korean info 심링크 누락 |
✅ | 심링크 추가. A안 libretro-core-info.mk와 파일 전체 diff 0 |
batocera-upgrade fsoverlay 사본 |
✅ | 541줄 삭제. 남은 fsoverlay 4종은 실제 보드 수정을 담은 것들만 남았고, 공용 파일의 local available 분리 수정(216–217행)은 유지 |
CI lint — overlay.py PEP 758 오진 |
✅ | 52523fc87e revert. ruff format --diff → already formatted, Python 3.14 파싱 정상 |
CI lint — aethersx2Generator.py |
✅ | TYPE_CHECKING 블록 unused import 6개 제거 → ruff check → All checks passed! |
CI도 통과했습니다(run 33239876041, lint·unit-tests 모두 pass). 4차 시점에 "A안 PR #1은 통과하는데 C안만 실패"하던 차이가 없어졌습니다.
승인 의견: 코드 기준으로 이 PR은 릴리스에 나갈 준비가 됐다고 봅니다. 셀프 PR이라 GitHub API로는 APPROVE 상태를 남길 수 없어 코멘트로 대신합니다.
남은 항목은 4차에서 릴리스를 막지 않는다고 분류한 python3.14 경로 하드코딩 하나뿐입니다(fsoverlay/usr/lib/python3.14/site-packages/configgen/generators/{duckstation,flycast}Generator.py). 다음 buildroot 파이썬 범프 때 조용히 무효화되는 구조라, 그때 확인 항목으로만 남겨두시면 되겠습니다.
1차부터 5차까지의 흐름을 돌아보면, 공용 파일을 직접 고치던 방식에서 board fsoverlay로 전환한 것이 가장 큰 개선이었습니다. 공용 Kconfig의 보드 프록시 게이팅(!BR2_PACKAGE_UBOOT_ODROID_M1)이 공유 rk3568 타겟 11개 보드의 rocknix-joypad를 떨어뜨리던 문제부터, 전 Wayland 보드의 Dolphin Qt GUI가 사라지던 문제까지 — 이 트랙이 다른 보드에 새지 않게 된 것이 이번 릴리스에서 가장 의미 있는 부분이라고 봅니다.
실기 부팅·성능·Vulkan 동작과 실제 이미지 내용물 확인은 여전히 정적 분석 범위 밖이며, 위 검증은 코드·설정 대조와 CI 결과, 로컬 ruff 재현에 근거합니다.
🤖 Reviewed by Claude Opus 5 (1M context)
Zansword was an incorrect name attached to the credit in an earlier session - the correct name/casing is DsNo. Also describe the patch more precisely: it's a CRC-tolerance fix (accepts Korean-translated ROMs that fail the standard CRC32 check), not a text/UI translation.
README-odroidm1.md -> README-odroidm1.ko.md (unchanged content, just renamed), plus a new README-odroidm1.en.md English translation. Both files cross-link to each other at the top. Using ISO 639-1 "ko"/"en" language codes rather than "kr" (that's the ISO 3166-1 country code for South Korea, not a language code).
…ADME's perf table
목적
A안(벤더 blob, g24p0)/B안(Panfrost)의 GPU 렌더 폴트(
DATA_INVALID_FAULT)와 Vulkan 실패(PanVK가 KHR_display 서피스 생성에서 막힘, v9 실기 확인)를 완전히 우회하는 세 번째 경로: 신형 통합 blob(g29p1, GLES+Vulkan)을 Wayland(labwc) 위에서 굴려 Vulkan을 실제로 화면에 출력하는 것이 목표. GameCube Dolphin Vulkan이 A/B 둘 다 실패한 유일 시스템이라 헤드라인 타겟이었음.브랜치 전략
A(
odroid-m1-bsp-kernel)는 시행착오 포함 106개 커밋이라 그대로 베이스로 쓰지 않고, A/B가 갈라지기 전 공통 조상 커밋(41f34e4dfd)에서 새로 분기. 이후 A(5개)/B(17개) 분기 커밋 중 GPU스택 무관 제네릭 fix 13개만 cherry-pick + PCSX2/Dolphin standalone 등 시스템 활성화 부분만 수동 재작성(PanVK 전용 줄 제외). 상세는 커밋 로그 참고.게이트 실험 (빌드 전 5분짜리 실기 검증)
vulkaninfo가 Mali-G52 정상 열거(driverID: DRIVER_ID_ARM_PROPRIETARY). 벤더 g25p0 kbase가 g29p1을 그대로 수용 → rocknix kbase 외부모듈 불필요, 커널 무변경 경량 경로 확정.eglInitialize가 g29p1에서 정상 동작. 본 빌드(blob 패키지 교체 + vulkan-loader/tools + labwc + vulkan-wsi-layer 추가) 진행 확정.현재 상태 — 전체 시스템 매트릭스 완료, 릴리스 준비 단계
본 빌드 완료, GameCube/Dreamcast/PS2/PSP/PSX/Saturn/N64/NDS 8개 시스템 전부 실기 스모크+실사용 테스트 완료. 이 브랜치는 총 60개 커밋(공통 조상
41f34e4dfd대비, AI 1·2차 리뷰 반영분 포함), 아래는 시스템별 최종 결론 요약:DATA_INVALID_FAULT를 완전 회피하는 AetherSX2(구형 GS 분기, Vulkan 강제)를 별도 코어로 추가해 실사용 확정(최저 29fps, NTSC 30fps 타겟 근접)세션 중 발견한 운영상 이슈:
hotkeygen데몬이 알 수 없는 기간 동안 죽어있어 핫키 컨텍스트 갱신이 조용히 실패하던 버그를 root-cause,S90hotkeygen재시작으로 해결(재부팅 후 생존 여부는 아직 재검증 필요).이번 커밋에 포함된 것 (요약)
vulkan-wsi-layer신규 패키지(KHR_display 전용 blob Vulkan을 Wayland 서피스로 브릿지) + Wayland surface/swapchain 레이스 컨디션 다수 수정melonds_dual_screenES 옵션) 지원 활성화FRAMETIME_LOG/FRAMETIME_LOG_VK) 추가 — env 미설정 시 완전 no-op, 눈대중 fps 대신 Avg/1% Low를 정량 측정하기 위한 것.tools/frametime-bench/참고AI 1차 리뷰 반영 (8개 커밋)
BATOCERA_TARGET_BSP_ODROIDM1Kconfig 심볼 신설(A/B에도 동일 적용, PR ODROID-M1 dedicated target: hardkernel BSP kernel + Mali-G52 blob + VU8M overlays #1·Panfrost GPU stack for ODROID-M1 (B안) — PanVK 서피스 생성 실패로 폐기 #3 참고),dolphin-emu.mk의 Wayland 커밋/패치 스왑을 이 심볼로 좁혀서 다른 Wayland 보드의 dolphin 다운그레이드+패치 유실 방지vulkan-wsi-layer를 bring-up용 Debug 빌드에서 Release로 되돌림 — 정밀 fps 벤치마크 전 필수였던 항목, 이제 해결돼서 벤치마크 바로 가능aethersx2:main브랜치 참조 → 커밋 고정 +.hash추가, 벤더.soprovenance 문서화(libpcap 우선순위 확인 포함 — 의도대로 동작 확인됨)labwc/rc.xml의 중복pcsx2-qtwindowRule 병합mali-g52-odroidm1/Config.in에 형제 패키지에 있던 DMA_BUF/FORMAT_MODIFIER select 보완.board의 rk3568/patches 재사용 안 하는 이유 주석이 부정확했던 것 수정 + provenance 파일 추가docker.mk의 존재하지 않는EXTRA_SRCDIR_MOUNTS언급 정리mali.icd.json의libmali.so.1심링크는 ldconfig가 SONAME 기반으로 실기에 이미 자동 생성 중 확인,melonds.mk의libinput의존성도 Config.in에 이미 정확히 대응하는 조건부 select 있음 — 둘 다 리뷰의 false positiveAI 2차 리뷰 반영
dolphin-emu.mk게이팅이 1차에서 절반만 적용됐던 것 수정 —DOLPHIN_EMU_VERSION/ENABLE_X11=OFF/VMA fix 3곳만 보드 전용 심볼로 좁혔고,ENABLE_QT=OFF/ENABLE_NOGUI=ON블록(64행)은 여전히 공용BR2_PACKAGE_BATOCERA_WAYLAND였음 — 그 결과 다른 Wayland 보드가 "새 커밋 + 구커밋용 NoGUI 강제"라는 어긋난 조합이 되고 있었음. 이 블록도 같은 심볼로 좁혀서 다른 Wayland 보드가 Qt6 경로로 정상 복귀하도록 수정melonds.mk가 여전히BR2_PACKAGE_MALI_G52_ODROIDM1을 판별자로 쓰는 것 — 이 심볼은 이 보드에서만=y라 다른 보드로 새는 문제는 없고, "이 보드"와 "blob GPU 쓰는 구성" 중 어느 쪽 의도인지 갈리는 문제라 리뷰에서도 급하지 않다고 명시함 — 이번엔 보류남은 작업
aethersx2Generator.py등 이번 세션 파이썬 변경이 린트/유닛테스트 한 번도 안 돎머지 대상 아님 — 개인 배포용 최종 빌드 진행 중인 draft, 리뷰/코멘트용.