PPM animation files

The container, metadata, thumbnail, frames, sound and signature area.

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]

Major sections of an ordinary PPM
PartWhat it contains
Header and metadataPARA, sizes, authors, lock state, filenames and date
Thumbnail64 × 48 indexed preview, arranged in 8 × 8 tiles
AnimationFrame offset table and compressed frame records
SoundPer-frame effect flags, audio header, BGM and three effects
TrailerSignature 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

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

OffsetFieldMeaning
0x00PARAContainer marker
0x0432-bit animation lengthMeasured from the animation header at 0x06A0
0x0832-bit sound lengthExtent of the sound section
0x0C16-bit final frame indexAdd one for the number of frames
0x0E16-bit versionOrdinary 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

MaskObserved use
0x02Loop playback
0x10Hide the first ink layer
0x20Hide the second ink layer
0x40Present in ordinary files
0x01, 0x04, 0x08Not 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 operationInterpretation supported by the comparisonEvidence and qualification
File offset 0x0CStored value + 1 = frame countThe Collective and parser explicitly add one; DSiBrew's table abbreviates this field as a frame count.
Author IDs at file offsets 0x56, 0x5E, 0x8AParent, current and root, respectivelyThe Collective field map and parser agree; the older DSiBrew author labels are not used here.
Frame-header bit 70: difference frame; 1: complete keyframeDSiBrew, the Collective's frame-header discussion and the parser agree. The Collective's later diffing paragraph reverses the description.
Type-two row payloadStart from ones, then write stored chunk bits unchangedThe Collective's algorithm and parser agree. DSiBrew's example implies a different inversion and should not replace that algorithm.
Nominal sound rate8,180 Hz before BGM speed adjustmentThe 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]

Sources

  1. [1] Flipnote Decompilation Project — PPM container and original serialisation
  2. [2] Flipnote Studio Docs — PPM format
  3. [3] hatena-server — PPM format
  4. [4] Flipnote Studio Docs wiki — PPM format
  5. [5] DSiBrew — Flipnote Files/PPM
  6. [6] flipnote.js — PPM parser and frame composition

← All documentation