Skip to content

Instantly share code, notes, and snippets.

@GMMan
Last active November 11, 2023 01:46
Show Gist options
  • Save GMMan/021e191cfc8f31733f1636a266b92fcd to your computer and use it in GitHub Desktop.
Save GMMan/021e191cfc8f31733f1636a266b92fcd to your computer and use it in GitHub Desktop.
Tamagotchi Smart file formats

Tamagotchi Smart File Formats

General notes

Because GeneralPlus chips tend to be 16-bit, or use peripherals derived from their 16-bit line, a word is generally 16-bits as well, even on systems that are 32-bit.

Tamagotchi archive

This is an archive file for storing multiple files, and is used on both Smart and Pix, and potentially other Tamagotchis. The file supports compression, but this is not used on the Smart. The file starts with the word 0x3232 signifying that this is an archive, followed by the number of files in the archive, as a word. Next is the file entries table, consisting of the same number of entries as number of files. This is the format of an entry:

struct arch_entry {
    uint32_t flags;
    uint32_t offset;
    uint32_t compressed_length;
    uint32_t decompressed_length;
};
  • flags: Usually stores whether file is compressed in the lower 4 bits. The following compression types are known:
    • 0: no compression
    • 1: LZ4 stream
    • 2: Zlib
    • 3: LZMA
  • offset: The byte offset relative to start of archive.
  • compressed_length: The compressed length of the file. If uncompressed, may be rounded up to 32-bit alignment for 16-bit systems.
  • decompressed_length: The length of the file when decompressed.

File data follows. Archives are also files, so you can nest archives inside each other. Data is padded with null bytes for alignment if necessary.

Tamagotchi content archive

Content archives are typically Tamagotchi archives consisting of 4 files:

  • 0: Data definitions
  • 1: Sprites
  • 2: TEXTs (unused on Tamagotchi Smart)
  • 3: Sounds (usually empty)

These can be found in Tamagotchi Pix's main resource archive, and individually on TamaSma Cards.

Data definition

WIP

The file starts with offsets to various tables. On Tamagotchi Smart, there are 20, while on Tamagotchi Pix, there are 18. On Tamagotchi Smart, the last offset refers to a word that contains the TamaSma Card number.

GeneralPlus PPU primer

Before talking about sprites, it's useful to know a few things about GeneralPlus picture processing units.

TEXTs and sprites

There are two kinds of images the PPU supports. A TEXT is a type of tile-based image that supports limited scrolling and is usually used for backgrounds. The advantage of TEXTs is you can define many tiles (characters) and specify charnums to build an image. Because of this, they are usually used for displaying text characters in a grid pattern. A sprite is a more flexible image consisting of a single character. It can be moved, rotated, scaled, faded, etc. On Tamagotchi Smart, all images are stored as sprites.

Palettes

Indexed images are used extensively, and as such, they require palettes to supply colors. Each color is in ARGB1555 format, where the alpha bit is flipped: 0 indicates opaque, and 1 indicates transparent. Palettes can be 4 to 256 entries long, and are stored in little endian order.

Characters

A character is a tile containing image data. They are a stream of palette indexes. Each pixel can be 2, 4, 6, or 8 bits wide. The bits are read MSB first. The pixels are row major.

Sprites package

This format stores sprites. It starts with four 32-bit byte pointers:

  • img_defs_offset: Offset to image definitions.
  • sprite_defs_offset: Offset to sprite definitions.
  • palettes_offset: Offset to palettes.
  • chars_offset: Offset to characters.

Note that this format primarily stores the starting offsets to elements, and usually not the number of elements. To figure out the number of elements, you need to sort the elements then find the number of elements between the current and next declared elements.

Image definitions

An image is a group of subimages consisting of sprites. Subimages are a related set of graphics, such as animated frames or a set of expressions. There is one or more subimage in an image. An image definition has the following structure:

struct image_def {
    uint16_t sprite_start_index;
    uint8_t width;
    uint8_t height;
    uint16_t palette_start_index;
};
  • sprite_start_index: The staring index of the sprites that make up the image. This is for the first subimage, and each subimage consists of one or more sprites.
  • width: The width of each subimage in sprites.
  • height: The height of each subimage in sprites.
  • palette_start_index: The starting index for the palette. An image may have more than one palette, shared across its subimages.

Note that the indexes are indexes, not offsets. Be sure to multiply index by the size of the desired data type when accessing.

Sprite definitions

The sprite definition is as follows:

struct sprite_def {
    uint16_t charnum;
    int16_t offset_x;
    int16_t offset_y;
    struct sp_attribute0 attribute;
};
  • charnum: The charnum or the sprite. This is used to calculating the starting offset into the characters data.
  • offset_x: The horizontal offset of the sprite relative to the pivot. A pivot is the canonical screen position of the image.
  • offset_y: The vertical offset of the sprite relative to the pivot.
  • attribute: Data for the sprite's Attribute0 register.

The Attribute0 register consists of the following:

struct sp_attribute0 {
    uint16_t sp_color:2;
    uint16_t sp_flip:2;
    uint16_t sp_hsize:2;
    uint16_t sp_vsize:2;
    uint16_t sp_palette:4;
    uint16_t sp_depth:2;
    uint16_t sp_blend:1;
    uint16_t quadruple:1;
};
  • sp_color: The color mode, or in other words how many bits per pixel in the character.
    • 0: 2bpp (4 colors)
    • 1: 4bpp (16 colors)
    • 2: 6bpp (64 colors)
    • 3: 8bpp (256 colors)
  • sp_flip: Flags indicating whether the sprite is flipped. Does not appear to be used on Tamagotchi Smart.
    • 1: Flipped horizontally
    • 2: Flipped vertically
  • sp_hsize: The character width.
    • 0: 8px
    • 1: 16px
    • 2: 32px
    • 3: 64px
  • sp_vsize: The character height. Same range as sp_hsize.
  • sp_palette: Selecte the palette bank. Values overridden when image loaded.
  • sp_depth: Drawing priority. Typically not set.
  • sp_blend: Whether blending is enabled. Typically not set.
  • quadruple: If set, width and height of image is quadrupled. Currently only encountered on Tamagotchi Pix. Note character offsets are not quadrupled.

Palettes

Palettes are stored in groups of 4 RGB1555 colors. They appear to be sorted from smallest to largest. Note there is up to 32 bytes of padding to keep characters 16-byte aligned.

Characters

Character data as described above. Use the following to calculate offset:

offset = (8 << spr.attribute.sp_hsize) * (8 << spr.attribute.sp_vsize)
         * (spr.attribute.color * 2 + 2) / 8 * spr.charnum;

Note that charnum 0 is never used.

TEXTs package

This kind of package stores TEXTs (character-based images, not to be confused with strings). Similar to the sprites package, it starts with four 32-bit offsets:

  • text_defs_offset: Offset to TEXT definitions.
  • charnums_offset: Offset to charnums.
  • palettes_offset: Offset to palettes.
  • chars_offset: Offset to characters.

TEXT definitions

A TEXT definition defines one TEXT image. It has the following structure:

struct text_def {
    uint32_t charnums_offset;
    uint32_t palette_index;
    uint16_t width;
    uint16_t height;
    uint16_t character_width;
    uint16_t character_height;
    uint16_t color;
    uint16_t reserved;
};
  • charnums_offset: Byte offset into charnums table. Note charnums are 16-bit aligned and LSB of offset will be ignored.
  • palette_index: Index into palettes. This is a color index, i.e. multiplied by 2 for byte offset.
  • width: Width of image in characters.
  • height: Height of image in characters.
  • character_width: Width of each character in pixels.
  • character_height: Height of each character in pixels.
  • color: The color mode; see sp_color in sprites package above.
  • reserved: Unused, probably alignment added by compiler.

Palettes

Palette entries are not grouped, and there are no padding colors at the end.

Characters

Characters are arranged the same as in sprite packages, however note that character widths and heights are in pixels, so adjust calculations accordingly. Note that charnum 0 is considered to be fully transparent.

Sounds archive

Sounds on Tamagotchi Smart are stored as GeneralPlus ALP/DRM files in a resource archive.

Text archive

Text on Tamagotchi Smart is stored in a resource archive as a single file. It starts with the number of text strings as a word. Following that is an array of words, indicating the word offsets of each string. After that is a blob of strings.

Each string consist of an array of word character indexes, terminated by a null word. Since 0 is used as the null terminator, characters are 1-indexed. Refer to the fonts for the characters available (the fonts are still 0-indexed).

There are special escape characters where the top 4 bits (0xf000) are set. 0xf000 represents a newline, the rest still need to be looked into.

(In case it isn't clear, because Tamagotchi Smart runs on a 16-bit CPU that does not have byte addressing, the offsets refer to word offsets, i.e. offset times 2 bytes. Each data element is also 16 bits.)

Tamagotchi Pix sprites package

Tamagotchi Pix has a second sprites package format. Its purpose is the same as the common sprites package, but has the additional feature of per-image compression. Because of the compression, the data layout is slightly different. Aside from compression, other notable differences include merging image and sprite definition into one structure, and only being able to use one size of sprite for the sprites that comprise the image.

The packages starts with one word indicating the number of images contained, and one word indicating the compression type. It is followed by an array of image definitions:

Image definitions

struct image_def {
    image_attribute attribute;
    uint16_t id;
    uint16_t subimage;
    uint16_t reserved;
    uint32_t pack_offset;
    uint32_t palettes_offset;
    uint32_t offsets_offset;
    uint32_t compressed_length;
    uint32_t data_length;
    void *resident;
};
  • attribute: Data regarding the image itself.
  • id: The ID of the image. The top 4 bits indicate which slot this image belongs to.
  • subimage: The subimage index. See the common sprites package above for information about subimages.
  • reserved: Unused. This is most likely space reserved by the compiler for alignment.
  • pack_offset: The byte offset of the compressed data in the package for this image.
  • palettes_offset: Offset in decompressed data for palettes.
  • offsets_offset: Offset in decompressed data for sprite offsets.
  • compressed_length: Length of compressed data in package.
  • data_length: Length of decompressed data.
  • resident: Pointer to resident copy of decompressed data. It is blank inside the package file.
struct image_attribute {
    uint16_t sp_color:2;
    uint16_t sp_hsize:2;
    uint16_t sp_vsize:2;
    uint16_t quadruple:1;
    uint16_t sprites_width:4;
    uint16_t sprites_height:4;
};
  • sp_color: See field in sp_attribute0 in common sprites package above.
  • sp_hsize: See field in sp_attribute0 in common sprites package above.
  • sp_vsize: See field in sp_attribute0 in common sprites package above.
  • quadruple: See field in sp_attribute0 in common sprites package above.
  • sprites_width: See width in image_def in common sprites package above.
  • sprites_height: See height in image_def in common sprites package above.

Palettes

Palettes follow the same rules as in the common sprites package, however there are no padding groups at the end. There may be several palettes in an image.

Characters

Characters also follow the same rules as in the common sprites package. Sprites are laid out by row; use this to calculate charnum. Charnum 0 is not skipped.

Compression

One of two compression algorithms are used to compress data. If compression type is 0, Zlib is used. Otherwise, LZ4 stream is used.

Tamagotchi Pix sound format

Sounds on Tamagotchi Pix are stored as an array of note entries, in the following format:

struct note {
    uint16_t duration;
    uint16_t preload;
    uint16_t ccp;
};
  • duration: The length of the note, in 1/100s unit. Sound ends when value is 0.
  • preload: Timer preload register value. Silence if value is 0.
  • ccp: CCP register value.

Sounds are generated as PWM waveforms. The frequency is calculated as:

srcClock / (65536 - preload)

and duty cycle is calculated as:

(ccp - preload + 1) / (65536 - preload)

The source clock is either 48MHz/256 or 96MHz/256, depending on the current system clock setting. Duty cycle usually ends up being around 10%.

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