A PPM begins with the four-byte PARA marker. The header gives animation and sound sizes, a zero-based last-frame index and a format value. Metadata follows, including lock state, a thumbnail-frame index and author fields. The 64 × 48 tiled thumbnail occupies the next 1,536 bytes. The animation header, frame offsets and compressed frame payload follow; sound flags and audio come afterwards. [1][2][3]
| Part | What it contains |
|---|---|
| Header and metadata | PARA, sizes, authors, lock state, filenames and date |
| Thumbnail | 64 × 48 indexed preview, arranged in 8 × 8 tiles |
| Animation | Frame offset table and compressed frame records |
| Sound | Per-frame effect flags, audio header, BGM and three effects |
| Trailer | Signature and padding |
File construction
The Flipnote Decompilation Project has traced the ARM9 serialiser in four builds, including the order in which it appends data. Japanese V1 and V2 differ in several places, including how audio lengths are rounded. A later packaging step adds a 0x90-byte trailer. When using an offset from the research, check whether it refers to the serialised body or the packaged file. [1]
Rendering and validation
Frame rows are compressed and may depend on the previous frame. Animation flags can hide either layer. The file also ends with a signature area, which the original client may check when accepting a modified file. Writing data into that area is not enough to establish validity. The serialisation steps have been traced, but a complete original signing workflow has not yet been established. [1][2]
Choose the layer you are implementing
- Metadata maps the root, parent and current author fields and the lock and thumbnail indexes. [1][2]
- Animation frames describes row compression, difference reconstruction and display. [2]
- Sound covers the four track lengths, speed bytes and effect flags. [1][2]
- Original serialisation documents the build-specific queue, field writes and mode decisions. [1]
- Packaging and acceptance follows the final trailer and the original open checks. [1]
Compute section boundaries with checked arithmetic before decoding any image or sound bytes. In particular, header +0x0C stores a zero-based last-frame index rather than a direct frame count. [1][2]
PPM header fields
| Offset | Field | Meaning |
|---|---|---|
0x00 | PARA | Container marker |
0x04 | 32-bit animation length | Measured from the animation header at 0x06A0 |
0x08 | 32-bit sound length | Extent of the sound section |
0x0C | 16-bit final frame index | Add one for the number of frames |
0x0E | 16-bit version | Ordinary Studio files use 0x24 |
Studio warns the creator when animation data reaches 736,800 bytes. That warning is an application limit; it does not tell us whether a larger file is safe to decode. The animation header starts at 0x06A0. Its first halfword is the offset-table length in bytes, the next two halfwords are still poorly understood, and the fourth contains playback and layer-visibility flags. Sound-effect flags start at 0x06A0 + animation_length, with one byte per frame. The audio header follows those flags at the next four-byte boundary. [4]
Animation flags
| Mask | Observed use |
|---|---|
0x02 | Loop playback |
0x10 | Hide the first ink layer |
0x20 | Hide the second ink layer |
0x40 | Present in ordinary files |
0x01, 0x04, 0x08 | Not established by the cited wiki |
Keep a hidden layer's bytes when decoding, even though the layer is not drawn. Frame-header bit 7 means 0 for a difference frame and 1 for a complete keyframe. The wiki gives these values in its header description, then reverses them in a later diffing paragraph. The frame decoding guide explains why the header description agrees with DSiBrew and the working decoder. [4]
Historical name and metadata presence
The extension comes from the working title Para Para Manga Koubou, translated in the format reference as Flipbook Workshop. The file's four-byte marker remains PARA. [2]
The metadata-read condition documented by the wiki is ((version & 0xF0) >> 4) != 0. Ordinary version 0x24 satisfies it. Check that condition before reading ordinary metadata from a file with the PARA marker. The source suggests the condition may be left over from development. [2]
At an animation length of 736,800 bytes or greater, Studio reports the size limit and stops further drawing or frame additions until space is recovered, for example by deleting a frame. This describes the editor's size limit. A third-party parser still needs its own allocation and bounds checks. [2]
The final 144 bytes
The published trailer description divides the final 0x90 bytes into a 128-byte RSA-1024 signature using SHA-1, followed by sixteen null bytes. The signed message is the preceding PPM body, excluding the trailer itself. Keep this trailer separate from the equally sized author-metadata block. Successfully decoding the frames does not test the signature. The original-code acceptance and packaging guide covers those checks separately. [2]
Differences between early and later references
DSiBrew records early observations and byte examples. Some labels and decoding instructions differ from later documentation. The table below uses the interpretation supported by both the Collective reference and the working PPM parser. It also notes contradictions within the references and differences in their display approximations; these do not establish separate file variants. [5] [2] [6]
| Field or operation | Interpretation supported by the comparison | Evidence and qualification |
|---|---|---|
| File offset 0x0C | Stored value + 1 = frame count | The Collective and parser explicitly add one; DSiBrew's table abbreviates this field as a frame count. |
| Author IDs at file offsets 0x56, 0x5E, 0x8A | Parent, current and root, respectively | The Collective field map and parser agree; the older DSiBrew author labels are not used here. |
| Frame-header bit 7 | 0: difference frame; 1: complete keyframe | DSiBrew, the Collective's frame-header discussion and the parser agree. The Collective's later diffing paragraph reverses the description. |
| Type-two row payload | Start from ones, then write stored chunk bits unchanged | The Collective's algorithm and parser agree. DSiBrew's example implies a different inversion and should not replace that algorithm. |
| Nominal sound rate | 8,180 Hz before BGM speed adjustment | The Collective and parser give 8,180; the older reference rounds this to 8 kHz. |
Decoded rows describe where a layer has ink. A zero mask bit leaves it transparent, allowing the other layer to show through. The older reference sometimes describes these as paper-coloured pixels, before the layers have been combined. The worked examples in the frame guide show the mask values before frame differencing and composition. [6]
