Skip to content

NFC reader interface (RETRO_ENVIRONMENT_GET_NFC_INTERFACE) with amiibo support - #19754

Draft
GavinDarkglider wants to merge 5 commits into
libretro:masterfrom
GavinDarkglider:nfc-reader-interface
Draft

GavinDarkglider wants to merge 5 commits into
libretro:masterfrom
GavinDarkglider:nfc-reader-interface

Conversation

@GavinDarkglider

@GavinDarkglider GavinDarkglider commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

What

A core-facing NFC tag reader interface, plus a frontend implementation that can serve tags from a physical reader or from amiibo dumps on disk. Cores that emulate an NFC reader (the 3DS amiibo reader is the motivating case) get real read/write tag access through the frontend instead of each core inventing its own file-drop.

The whole frontend side is opt-in (--enable-nfc, default off). The libretro.h additions are header-only and unconditional, like the other interfaces.

The interface (libretro.h)

RETRO_ENVIRONMENT_GET_NFC_INTERFACE = 99 | RETRO_ENVIRONMENT_EXPERIMENTAL, filling a struct retro_nfc_interface of function pointers (same pattern as LED/rumble/sensor).

  • Raw and encryption-agnostic. Tag memory is passed byte-for-byte; amiibo crypto stays in the core.
  • Versioned and negotiated. The core writes the version it was built against; the frontend lowers it and fills only those pointers, so the struct can grow without a newer frontend writing past an older core's struct.
Version Adds
v1 start_scan, stop_scan, get_status, get_tag_info, read, write
v2 set_source (hardware reader vs. software dumps)
v3 get_source_count, get_source_info, select_source
v4 has_hardware (live; a reader can come and go with a controller)

Frontend (nfc/)

A small dispatcher over pluggable backends:

  • amiibo (default): serves dumps from the new Amiibo directory (recursive scan, non-amiibo-sized files skipped). Nothing auto-loads; a tag is placed by the core's v3 enumeration or the menu picker. Writes are flushed back to the dump, so in-game save-back persists.
  • afnfc (--enable-nfc_afnfc, Linux): driver-agnostic hardware backend using only the kernel NFC generic-netlink family and AF_NFC raw sockets (what neard uses), so it works with any reader on the Linux NFC stack. It does not need or start neard. Tested with a pn533 USB reader and the Nintendo Switch Joy-Con reader.
  • file (testing, RETRO_NFC_BACKEND=file): a single .bin, to exercise the core path without hardware.

Menu

  • Settings > Directory > Amiibo. Defaults to <system>/amiibo.
  • Quick Menu > Load Amiibo. A .bin picker using the normal settings file browser. Picking a dump places it on the virtual reader and returns straight to the game, since tapping an amiibo is an in-game action. The menu stack is flushed to the Quick Menu first, so reopening the menu lands there.
  • Load Amiibo is shown only when the running core uses the NFC interface and the active source is software. When a core switches source while the menu is open, the current list is rebuilt immediately, so the entry appears or disappears without reopening the menu.

Both entries are compiled out without HAVE_NFC.

Commits

  1. libretro: add NFC reader interface (GET_NFC_INTERFACE)
  2. nfc: add NFC reader module with software, file and AF_NFC backends
  3. runloop: wire GET_NFC_INTERFACE and track NFC-capable cores
  4. build: add HAVE_NFC and HAVE_NFC_AFNFC options (also griffin)
  5. menu: add Amiibo directory setting and Load Amiibo picker

Each commit builds on its own.

Testing

  • Built on Linux at every commit, with and without --enable-nfc --enable-nfc_afnfc. NFC sources are C89-clean (-std=gnu89 -Wdeclaration-after-statement) and build in the griffin unity build.
  • Software backend: enumeration, explicit placement, fresh-tap status sequence, read/write with flush-back, hardware fallback when no reader is present, and release on core unload.
  • On hardware: Lakka on Nintendo Switch, with the Joy-Con NFC reader and a pn533 USB reader through the AF_NFC backend, and a 3DS core (Azahar) picking up amiibo through the software picker.

Notes for reviewers

  • 99 was the next free experimental slot when this was written. Happy to renumber if something else lands first.
  • The core-side consumer (3DS cores) will follow in their own repos once the interface shape is agreed.

GavinDarkglider and others added 5 commits October 8, 2026 21:33
Add RETRO_ENVIRONMENT_GET_NFC_INTERFACE (99 | EXPERIMENTAL), a
core-facing interface to an NFC tag reader, so cores that emulate an
NFC reader (e.g. the 3DS amiibo reader) can read and write real or
virtual NTAG21x / ISO14443-3A tags through the frontend instead of
each core inventing its own file-drop mechanism.

The interface is raw and encryption-agnostic: tag memory is passed
byte-for-byte, and any tag-format crypto (amiibo keys etc.) stays in
the core. It is versioned and negotiated -- the core writes the
version it was built against, the frontend lowers it to what it
provides and fills only those function pointers, so the struct can
grow without a newer frontend writing past an older core's struct:

  v1  start_scan / stop_scan / get_status / get_tag_info / read / write
  v2  set_source (hardware reader vs. software tag dumps)
  v3  get_source_count / get_source_info / select_source (enumeration)
  v4  has_hardware (live query; a reader can come and go at runtime)

Header-only; nothing in the frontend uses it yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EH8JM8RHaQNWidqraaPaf3
Frontend side of GET_NFC_INTERFACE: a small dispatcher
(nfc/nfc_frontend.c) over pluggable backends (nfc/nfc_backend.h).

- amiibo (default, software): serves raw amiibo/NTAG dumps from the
  Amiibo directory, scanned recursively (non amiibo-sized files are
  skipped) and enumerated by file name. A dump is placed explicitly
  -- by index through the v3 enumeration or by path from the menu
  picker -- never auto-loaded. Every start_scan re-arms as a fresh
  tap, and writes are flushed back to the dump so game save-back /
  registration persists.

- file (testing): a single .bin selected with RETRO_NFC_BACKEND=file
  and RETRO_NFC_TAG_FILE, to exercise the environ -> core ->
  read/write path without a reader.

- afnfc (Linux, NFC_HAVE_AFNFC): driver-agnostic hardware backend
  speaking only the kernel NFC generic-netlink family and AF_NFC raw
  sockets (the same interface neard uses), so it works with any
  adapter on the Linux NFC stack (tested with a pn533 USB reader and
  the Nintendo Switch Joy-Con/Pro Controller reader). It does not
  need or start neard. Tags are acquired on demand around each
  read/write (DEV_UP + START_POLL -> TARGETS_FOUND -> connect) so a
  transfer fits inside a tag's hold window. Hardware availability is
  probed live (cached ~1s), so set_source(HARDWARE) and the hardware
  enumeration slot only apply while a reader is actually connected,
  falling back to software otherwise.

Not built or wired up yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EH8JM8RHaQNWidqraaPaf3
Answer RETRO_ENVIRONMENT_GET_NFC_INTERFACE when built with HAVE_NFC
(otherwise return false so cores fall back), negotiating the interface
version as documented in libretro.h.

Point the software backend at the configured Amiibo directory,
defaulting to <system>/amiibo when none is set. Remember that the
running core asked for the interface (runloop_core_supports_nfc(), used
by the menu), and release the reader and that flag on core deinit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EH8JM8RHaQNWidqraaPaf3
HAVE_NFC (default off, --enable-nfc) builds the NFC reader module and
the software amiibo backend. HAVE_NFC_AFNFC (default off,
--enable-nfc_afnfc; Linux only, requires HAVE_NFC) adds the kernel
AF_NFC hardware backend. Also hooked into the griffin unity build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EH8JM8RHaQNWidqraaPaf3
Add an Amiibo directory (Settings > Directory) and a "Load Amiibo"
entry in the Quick Menu, so amiibo dumps can be swapped while a game
runs.

"Load Amiibo" is a .bin-filtered path setting
(settings_def_amiibo_file_path.h) opened in the regular settings file
browser, like Video Filter / Audio DSP. Picking a file serves it to
the software backend via CMD_EVENT_NFC_LOAD_AMIIBO, then flushes the
menu back to the Quick Menu and resumes content -- placing a tag is an
in-game action, so the player lands back in the game rather than in a
settings list.

The entry is shown only when the running core uses the NFC interface
and the active source is software. Because a core can switch between
the hardware reader and software dumps while the menu is open, the NFC
module now asks the menu to rebuild its current list whenever the
active source kind changes, so the picker disappears/appears
immediately instead of only after the menu is reopened.

The software backend now uses the configured Amiibo directory, falling
back to <system>/amiibo when it is left at its default.

Both entries are compiled out of the menu without HAVE_NFC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EH8JM8RHaQNWidqraaPaf3
@GavinDarkglider
GavinDarkglider marked this pull request as draft October 9, 2026 04:05
@GavinDarkglider

Copy link
Copy Markdown
Contributor Author

Sorry, I pushed v4, and actually added mifare support for Skylanders/disney infinity support in v5, then had Claude port the wrong version forward. Lol. Will rebase, and force push when it is done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant