/* **************************************************************************** * libcasio/format/std.h -- the CASIO "standard" file format description. * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey * * This file is part of libcasio. * libcasio 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. * * libcasio 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 libcasio; if not, see . * ************************************************************************* */ #ifndef LIBCASIO_FORMAT_STD_H # define LIBCASIO_FORMAT_STD_H # include "../cdefs.h" # pragma pack(1) CASIO_BEGIN_NAMESPACE /* This format is used by CASIO with its calculator for storing things * like add-ins (compiled programs), MCS (main memory saves), and others. * In fact, there is no name for the general format, only names for the * "subformats" based on this one (which are mainly made of their extensions, * such as G1M or G3P). */ /* --- * Standard Header. * --- */ /* It all starts with a header, called Standard Header by Simon Lothar. * This Standard Header contains the total filesize, the standard type (add-in, * MCS, e-acts), some data that will be useful for the MCS type, and some * magic and control bytes. * * For some reason, this StandardHeader is INVERTED on every file it's on, * you will have to apply a NOT operation on its bytes for it to make sense. * Keep in mind that, everywhere in the header, multi-bytes integers * are BIG ENDIAN. * * The LSB is the Least Significant Byte: once adapted to the host endianness, * it can simply be obtained by bitwise-AND-ing with 0xff. */ typedef struct casio_standard_header_s { /* the file identifier */ casio_uint8_t casio_standard_header_main_id[8]; /* our subtype! */ casio_uint8_t casio_standard_header_subtype[6]; /* first control byte: filesize LSB + 0x41 */ casio_uint8_t casio_standard_header_control; /* said to be 0x01, but doesn't need to */ casio_uint8_t casio_standard_header_align_one; /* total filesize */ casio_uint32_t casio_standard_header_filesize; /* second control byte: filesize LSB + 0xb8 */ casio_uint8_t casio_standard_header_control2; /* alignment */ casio_uint8_t casio_standard_header__align0; /* sum of 8 16-bit values starting at 0x300? */ casio_uint8_t casio_standard_header_checksum[2]; /* alignment */ casio_uint8_t casio_standard_header__align1[4]; /* is obfuscated - useful for G3P */ casio_uint8_t casio_standard_header_obfuscated0; casio_uint8_t casio_standard_header_obfuscated1; /* number of objects contained (useful for MCS filetype) */ casio_uint16_t casio_standard_header_number; } casio_standard_header_t; /* At the beginning, we thought "USBPower" was some magic sequence we would * systematically find in the "main_id" field. But counter examples came: * the G3L, whose main ID was "Ly755 ", and the C2P. * * We also thought the subtype was only one-byte long, but the C2P came along * with its "c2p\0\0\0" subtype. * All main ID/types correspondances are in the `src/utils/type.c` file. * From a user program, you can use the functions * in `include/libcasio/formatutils.h`. * * After the Standard Header is read and the type is read, we have parts, * each with their own subheaders and their own subtilities. */ /* --- * Standard Subheader. * --- */ /* Some Prizm/Classpad-related formats (language, fkeys, add-ins) use a * common subheader followed by a platform-specific subheader (which is the * same size of Prizm and Classpad, but doesn't seem to have the same * field organization). Here is the common subheader structure: */ typedef struct casio_standard_subheader_s { /* checksum */ casio_uint32_t casio_standard_subheader_checksum; /* file type: * - 0x00: picture (not used with this header); * - 0x01: add-in; * - 0x02: function keys; * - 0x04: language files; */ casio_uint8_t casio_standard_subheader_filetype; /* platform: * - 0x00: fx-CP; * - 0x01: Prizm */ casio_uint8_t casio_standard_subheader_platform; /* unknown */ casio_uint8_t casio_standard_subheader__unknown0[4]; /* size of the data + footer? */ casio_uint32_t casio_standard_subheader_df_size; /* control: * - for a G3A: filesize - 0x7000 - 4 * - for a C1A: filesize - 0x1000 - 4 */ casio_uint32_t casio_standard_subheader_control; /* unknown */ casio_uint8_t casio_standard_subheader__unknown1[4]; /* message zone size - unreliable (valid could have zero) */ casio_uint32_t casio_standard_subheader_message_zone_size; /* model; for C1A: GY437 */ casio_uint8_t casio_standard_subheader_models[6]; /* title/language name */ casio_uint8_t casio_standard_subheader_title[28]; /* filesize */ casio_uint32_t casio_standard_subheader_filesize; /* internal name */ casio_uint8_t casio_standard_subheader_internal_name[11]; /* language labels */ casio_uint8_t casio_standard_subheader_labels[8][24]; /* eAct strip flag (0x00: can't be used, 0x01: can be used) */ casio_uint8_t casio_standard_subheader_eact_strip_flag; /* unknown */ casio_uint8_t casio_standard_subheader__unknown2[4]; /* version: MM.mm.ffff */ casio_uint8_t casio_standard_subheader_version[10]; /* unknown */ casio_uint8_t casio_standard_subheader__unknown3[2]; /* timestamp: YYYY.MMDD.HHmm */ casio_uint8_t casio_standard_subheader_timestamp[14]; } casio_standard_subheader_t; /* Here is the Prizm-specific subheader: */ typedef struct casio_standard_prizm_subheader_s { /* unknown */ casio_uint8_t casio_standard_prizm_subheader__unknown0[38]; /* eAct strip labels */ casio_uint8_t casio_standard_prizm_subheader_eact_strip_labels[8][36]; /* eAct icon */ casio_uint8_t casio_standard_prizm_subheader_icon[0x300]; /* unknown stuff */ casio_uint8_t casio_standard_prizm_subheader__unknown1[0x90C]; /* language name (null terminated?) */ casio_uint8_t casio_standard_prizm_subheader_language_name[16]; /* language salutation (null terminated?) */ casio_uint8_t casio_standard_prizm_subheader_language_salutation[16]; /* filename (extension included) */ casio_uint8_t casio_standard_prizm_subheader_filename[0x144]; } casio_standard_prizm_subheader_t; /* And here is the Classpad-specific subheader: */ typedef struct casio_standard_classpad_subheader_s { /* unknown */ casio_uint8_t casio_standard_classpad_subheader__unknown0[0x46]; /* the C1A filename */ casio_uint8_t casio_standard_classpad_subheader_filename[0x144]; /* unknown */ casio_uint8_t casio_standard_classpad_subheader__unknown1[0x2C]; /* icon (maybe 46x30 pixels? packed 1-bit) */ casio_uint8_t casio_standard_classpad_subheader_icon[172]; /* unknown */ casio_uint8_t casio_standard_classpad_subheader__unknown2[0xC54]; } casio_standard_classpad_subheader_t; /* Also, if the platform is the Prizm, there is a footer at the end of the * file, which is only made of a 32-bit checksum that should be equal to * the subheader checksum. */ /* --- * Standard Picture Header. * --- */ /* Picture formats (C2P, G3P) have a common picture standard subheader, which * is the following: */ typedef struct casio_standard_picheader_s { /* magic sequence: "CC" for the Classpad, "CP" for the Prizm */ casio_uint8_t casio_standard_picheader_cp[2]; /* "0100", either in raw (0x00, 0x01) for G3P * or in ASCII (0x30, 0x31) for C2P */ casio_uint8_t casio_standard_picheader_magic[4]; /* magic sequences: * - "ColorCP\0" for the C2P; * - "LY755\0\0\0" for the G3P. */ casio_uint8_t casio_standard_picheader_magic2[8]; /* unknown byte: 0x02 on the G3P, 0x00 on the C2P */ casio_uint8_t casio_standard_picheader__unknown0; /* unused byte */ casio_uint8_t casio_standard_picheader__unused; /* filesize after the StandardHeader */ casio_uint32_t casio_standard_picheader_filesize; /* "Always contains the 32-bit big-endian integer 0x00000001" */ casio_uint32_t casio_standard_picheader__alwaysone; /* subsize (what's after the standard picture header) */ casio_uint32_t casio_standard_picheader_subsize; /* unknown gap */ casio_uint8_t casio_standard_picheader__unknown2[0x7C]; } casio_standard_picheader_t; /* Then we have the specific header -- see `libcasio/format/std/picture.h`. */ /* --- * Flavors. * --- */ /* Where do you want to go next? Pick your poison. */ CASIO_END_NAMESPACE # pragma pack() # include "std/addin.h" # include "std/eact.h" # include "std/mcs.h" # include "std/picture.h" # include "std/lang.h" # include "std/fkey.h" #endif /* LIBCASIO_FORMAT_STD_H */