Local library scanning

Follow reads, SD enumeration, name classification and list ordering by build.

Studio's library has a reader and media scanner distinct from the editor save path. A PPM can exist on storage and still fail to appear because its directory record was skipped, its name was grouped differently, the byte read failed, or later acceptance rejected it. Diagnose those stages in order instead of treating an empty library screen as one parser result. [1]

Reading a selected local file

BuildRead wrapperPath readCore readSD scanList sort
JP V10201392402013BD802013C3C0201D680020195EC
JP V20201844C0201873002018794020217AC020098BC
US V2020183F8020186DC020187400202126402009998
EU V20201847402018758020187BC020213EC020098D8

The local PPM load path allocates 0x100090 bytes and uses a size-zero read request, with special handling for download_tmp. The reader recognises public and SD path namespaces; JP V1 also has a private-data branch. The core opens in mode 1 and applies its size guard only for size-zero requests. It closes after reading, and a failed close returns zero. In a narrow JP V1 route a failed read followed by successful close can still report success; V2 requires both read and close success. The separate acceptance routine then interprets the buffered file. [1]

Enumerating removable media

The scan routine opens sdmc:/ in mode 1. Open error 12 maps to status 6; other open errors map to status 4. In JP V1 this routine checks statuses 3 and 5, closes the directory and returns. V2 status 5 clears lists and walks 368-byte directory records via BeginDirectory/Next. It considers a record when the word at record +280 is nonzero and bit 0 of the word at +284 is clear, then updates three lists. These conditions explain which records the enumerator keeps. The mapping to every visible library category remains incomplete. [1]

V2 basename grouping

  • The component after the final slash must be non-empty and no more than 28 bytes.
  • Four exact names are excluded: gif, 4B47554A, 4B475545 and 4B475556. These are equality tests, not substring filters.
  • Class 0 is exactly three decimal digits from 001 to 999.
  • Class 1 is eight decimal digits with year 2000–2099, month 1–12 and day 1–31. It does not validate the actual days in a month; even an impossible calendar date can pass that branch.
  • Other accepted basenames enter class 2. The mapping from these classes to every on-screen label is not fully established. [1]

List updates and order

The V2 list-update routine allocates 4,000-byte and 1,000-byte arrays for each index but processes only indices 0 and 1. It reads the list count from data +12, converts names to numeric keys and commits with a reverse flag. The observed body has no allocation-failure check or 1,000-entry bound check. JP V1's clear routine instead loops over four containers, so the three-list V2 model cannot simply be projected backward. [1]

The sort is an in-place selection sort over unsigned numeric keys, carrying a parallel permutation. It is capped at 2,000 entries and is not stable: equal-key records can change relative order. Visible labels are loaded separately. To compare a custom library against the original, check the filtered candidate set, numeric keys and permutation before comparing the final UI order. [1]

Filename identity is yet another step

The temporary-input dispatcher uses a build-specific path predicate. It starts with a six-character uppercase hexadecimal candidate from identifier bytes 3–5, then can try a check-character variant using a base-36 alphabet. JP V2 and EU V2 have another candidate from the low 24 bits of a separate value; US V2 and JP V1 do not. This is a path acceptance rule, not a proof of account ownership or a complete algorithm for generating IDs. The buffered acceptance guide covers the later body/trailer checks. [1]

Sources

  1. [1] Flipnote Decompilation Project — Saving, loading and library indexing

← All documentation