Save controller and worker

Trace a Save action through editor commit, background processing and file close.

Saving runs through a controller and a background worker. The button handler does not write the file synchronously. The studied V2 save page can choose one or several destinations, commit a dirty or uncached working frame, show a WaitWindow, and later display completion or error. A worker message performs the expensive processing. Distinguish the user's tap, a queued request, a successfully written file and a file the library accepts. [1]

Save functions by build

BuildTransaction preparationDestination processorPublic writerSD writer
JP V10201CC5C0201CDC002013B1C02020018
JP V202020D8802020EEC0201867402024298
US V202020840020209A40201862002024098
EU V2020209C802020B2C0201869C02023ED8

Preparation records context and mode, reserves a 1 MiB staging allocation if needed, resets size and selects an 18-byte record for modes 2, 4 or 5. Its return value may still be 1 after an allocation failure, so a caller must not equate that number with a usable staging buffer. The processor chooses between dataPub:, sdmc: and transport output. These are original control-flow observations for the specific builds, not a recommendation to duplicate their error handling. [1]

V2 save-page states

The V2 save page is scene mode 14. In US V2 its constructor is 020522E4, creates a 176-byte object and registers factory 11 and primary slot 12. The single-destination state is 020524D0, the multiple-destination state 02052584, Choose 0205270C, Select 02052730, Save 02052974 and Error 02052DA4. Their Japanese V2 and European V2 peers are mapped; an equivalent Japanese V1 save-page scene has not been established. US preparation at 02026BA8 commits a dirty or uncached current frame and normalises destination zero to four before serialisation. [1]

What the file writer does

The public and SD write cores create a target with a path, mode value 3 and an option, open it in mode 2, seek to zero, write the requested bytes and close. Create/open failure exits without a close. Seek or write failure attempts one close and ignores that close result. On the successful route, the close result determines success. The underlying byte-write wrapper flushes cache, locks its service, invokes the SDK write, unlocks and requires the returned byte count to match exactly; a short write produces category 1, code 5. [1]

Mode 4's public wrapper adds .ppm only when the substring is absent anywhere in the proposed name. A name containing those four characters in the middle can therefore bypass suffix addition. This is an observed string check, not a safe naming policy for a new service. The successful recorder stores public and SD path buffers plus their pointers in transaction state. [1]

Worker completion and diagnosis

The original worker uses a single-message queue. Request 1 processes a save and clears busy state without directly forwarding the processor result; request 2 scans media. The analysed worker has a 0x2000 stack and priority 12. This makes a UI transition or cleared spinner an incomplete success signal. To diagnose a failed save, follow the controller state, current-frame commit, queue insertion, serialiser length, package result, selected destination, exact write count, close result and a fresh library read. [1][2]

Sources

  1. [1] Flipnote Decompilation Project — Saving, loading and library indexing
  2. [2] Flipnote Decompilation Project — PPM container and original serialisation

← All documentation