/* ***************************************************************************** * libg1m/format/picture.h -- the G1M picture formats description. * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey * * This file is part of libg1m. * libg1m is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3.0 of the License, * or (at your option) any later version. * * libg1m is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libg1m; if not, see . * ************************************************************************** */ #ifndef LIBG1M_FORMAT_PICTURE_H # define LIBG1M_FORMAT_PICTURE_H # include /* ************************************************************************** */ /* G3P: pictures for Prizm */ /* ************************************************************************** */ /* G3P are pictures for fx-CG. They only have one part. * This mysteries over this format have been unraveled by many, but I'm using * Simon Lothar's documentation and Kerm Martian's articles. * * Some color depth things: */ enum g3p_colorsize { g3p_color_4bit = 0x03, g3p_color_16bit = 0x10 }; /* So, after the header, here is the G3P subheader: */ struct g3p_subheader { /* some magic sequence: "CP0100Ly755" * "CP" is check by a syscall */ uint8_t magic[11]; /* unused */ uint8_t unused[5]; /* size of the file after standard header */ uint32_t g3p_size; /* undocumented */ uint8_t unknown[4]; /* size of the image data + 0x18 bytes of header */ uint32_t image_size; /* undocumented gap */ uint8_t undocumented_gap[124]; }; /* What is after the G3P subheader is the image (data). * * The image has a header, some data and a footer. Here is the header: */ struct g3p_imageheader { /* magic sequence? is: 0x00, 0x01, 0x00, 0x00 */ uint8_t magic[4]; /* size of the image data + footer */ uint32_t df_size; /* w0t */ uint16_t unknown2; /* width */ uint16_t width; /* height */ uint16_t height; /* color depth - see `g3p_colorsize` */ uint16_t color_depth; /* undocumented, again */ uint32_t undocumented; /* length of image + footer */ uint32_t data_size; }; /* Then there is the image data and the footer. * * At the beginning of the image data, there is a 2-byte ID. * 0x3c1b is the ID for "Casio Provided" images with no footers (?). * * The image is deflated using the DEFLATE algorithm. * * For some images, CASIO added some obfuscation. To check if the image is * encrypted, according to syscalls, you have to check standard header data. * Image is encrypted if: * * [0x1C] != [0x08] + [0x12] + [0x13] + 0x7B * * Which, simplified and with our structures, is: * * (std.obfuscated + 8) & 0xff != (std.filesize & 0xff00) >> 8 * * then the deflated image is encrypted. * * If this is the case, before passing the data to the INFLATE algorithm, * you have to apply this on each byte of the deflated image: * * 0b76543210 -> 0b21076543, * which, in C, is: (byte >> 3) | ((byte & 0x7) << 5) * * The footer contains the Adler32 checksum of the raw and unobfuscated data. * Here it is: */ struct g3p_imagefooter { /* checksum */ uint32_t checksum; }; /* ************************************************************************** */ /* C2P: Images for Classpads */ /* ************************************************************************** */ /* C2P are images for fx-CP400 calculators. It starts of with this header: */ struct c2p_subheader { /* magic field: "CC0100" */ uint8_t magic1[6]; /* second magic: "ColorCP\0\0\0" */ uint8_t color_cp[10]; /* filesize without standard header */ uint32_t c2p_size; /* unknown */ uint32_t unknown; /* filesize - 0x234 */ uint32_t unknown_size; /* undocumented */ uint8_t undocumented[124]; /* "0100" */ uint8_t zero_one_zero_zero[4]; /* filesize - 0x254 */ uint32_t unknown_size2; /* unknown */ uint16_t unknown2; /* width (max for screen: 0x136 */ uint16_t width; /* height (max for screen: 0x191) */ uint16_t height; /* undocumented, again */ uint8_t undocumented2[18]; /* filesize - 0x258 */ uint32_t unknown_size3; }; /* Then there is the zlib header with default compression. * The pixels format is R5G6B5. * * After the image, there is a footer, which is mainly undocumented, but * here is what we've got: */ struct c2p_footer { /* "0100", again */ uint8_t zero_one_zero_zero[4]; /* and some undocumented stuff */ uint8_t undocumented[358]; }; # pragma pack() #endif /* LIBG1M_FORMAT_PICTURE_H */