113 lines
3.1 KiB
C
113 lines
3.1 KiB
C
/* ************************************************************************** */
|
|
/* _____ _ */
|
|
/* libg1m/format/picture_cg.h |_ _|__ _ _| |__ ___ _ _ */
|
|
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
|
/* | | (_) | |_| | | | | __/ |_| | */
|
|
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
|
/* Last updated: 2016/11/02 14:15:46 |___/ */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
#ifndef LIBG1M_FORMAT_PICTURE_CG_H
|
|
# define LIBG1M_FORMAT_PICTURE_CG_H
|
|
# include <stdint.h>
|
|
|
|
/* These 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 and Kerm Martian's documentations.
|
|
*
|
|
* 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 != (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;
|
|
};
|
|
|
|
# pragma pack()
|
|
#endif /* LIBG1M_FORMAT_PICTURE_CG_H */
|