2017-02-28 17:08:52 +01:00
|
|
|
/* *****************************************************************************
|
|
|
|
* libg1m/format/std.h -- the CASIO "standard" file format description.
|
|
|
|
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
|
|
|
|
*
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
* ************************************************************************** */
|
|
|
|
#ifndef LIBG1M_FORMAT_STD_H
|
|
|
|
# define LIBG1M_FORMAT_STD_H
|
|
|
|
# include <stdint.h>
|
|
|
|
# pragma pack(1)
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*
|
|
|
|
* It all starts with a header, called Standard Header by Simon Lothar.
|
|
|
|
* This Standard Header contains the total filesize, the G1M 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. */
|
|
|
|
|
|
|
|
struct standard_header {
|
|
|
|
/* the file identifier */
|
|
|
|
uint8_t main_id[8];
|
|
|
|
|
|
|
|
/* our subtype! */
|
|
|
|
uint8_t subtype[6];
|
|
|
|
|
|
|
|
/* first control byte: filesize LSB + 0x41 */
|
|
|
|
uint8_t control;
|
|
|
|
|
|
|
|
/* said to be 0x01, but doesn't need to */
|
|
|
|
uint8_t align_one;
|
|
|
|
|
|
|
|
/* total filesize */
|
|
|
|
uint32_t filesize;
|
|
|
|
|
|
|
|
/* second control byte: filesize LSB + 0xb8 */
|
|
|
|
uint8_t control2;
|
|
|
|
|
|
|
|
/* alignment */
|
|
|
|
uint8_t align[8];
|
|
|
|
|
|
|
|
/* is obfuscated - useful for G3P */
|
|
|
|
uint8_t obfuscated;
|
|
|
|
|
|
|
|
/* number of objects contained (useful for MCS filetype) */
|
|
|
|
uint16_t number;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* 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/libg1m/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.
|
|
|
|
*
|
2017-03-17 22:23:55 +01:00
|
|
|
* 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: */
|
|
|
|
|
|
|
|
struct standard_subheader {
|
|
|
|
/* checksum */
|
|
|
|
uint32_t checksum;
|
|
|
|
|
|
|
|
/* file type:
|
2017-03-18 08:16:14 +01:00
|
|
|
* - 0x00: picture;
|
2017-03-17 22:23:55 +01:00
|
|
|
* - 0x01: add-in;
|
|
|
|
* - 0x02: function keys;
|
|
|
|
* - 0x04: language files; */
|
|
|
|
uint8_t filetype;
|
|
|
|
|
|
|
|
/* platform:
|
|
|
|
* - 0x00: fx-CP;
|
|
|
|
* - 0x01: Prizm */
|
|
|
|
uint8_t platform;
|
|
|
|
|
|
|
|
/* unknown */
|
2017-03-18 08:16:14 +01:00
|
|
|
uint8_t _unknown0[4];
|
|
|
|
|
|
|
|
/* size of the data + footer? */
|
|
|
|
uint32_t df_size;
|
2017-03-17 22:23:55 +01:00
|
|
|
|
|
|
|
/* control:
|
|
|
|
* - for a G3A: filesize - 0x7000 - 4
|
|
|
|
* - for a C1A: filesize - 0x1000 - 4 */
|
|
|
|
uint32_t control;
|
|
|
|
|
|
|
|
/* unknown */
|
|
|
|
uint8_t _unknown1[4];
|
|
|
|
|
|
|
|
/* message zone size - unreliable (valid could have zero) */
|
|
|
|
uint32_t message_zone_size;
|
|
|
|
|
|
|
|
/* model; for C1A : GY437 */
|
|
|
|
uint8_t models[6];
|
|
|
|
|
|
|
|
/* title/language name */
|
|
|
|
uint8_t title[28];
|
|
|
|
|
|
|
|
/* filesize */
|
|
|
|
uint32_t filesize;
|
|
|
|
|
|
|
|
/* internal name */
|
|
|
|
uint8_t internal_name[11];
|
|
|
|
|
|
|
|
/* language labels */
|
|
|
|
uint8_t labels[8][24];
|
|
|
|
|
|
|
|
/* eAct strip flag (0x00: can't be used, 0x01: can be used) */
|
|
|
|
uint8_t eact_strip_flag;
|
|
|
|
|
|
|
|
/* unknown */
|
|
|
|
uint8_t _unknown2[4];
|
|
|
|
|
|
|
|
/* version: MM.mm.ffff */
|
|
|
|
uint8_t version[10];
|
|
|
|
|
|
|
|
/* unknown */
|
|
|
|
uint8_t _unknown3[2];
|
|
|
|
|
|
|
|
/* timestamp: YYYY.MMDD.HHmm */
|
|
|
|
uint8_t timestamp[14];
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Here is the Prizm-specific subheader: */
|
|
|
|
|
|
|
|
struct _prizm_subheader {
|
|
|
|
/* unknown */
|
|
|
|
uint8_t _unknown4[38];
|
|
|
|
|
|
|
|
/* eAct strip labels */
|
|
|
|
uint8_t eact_strip_labels[8][36];
|
|
|
|
|
|
|
|
/* eAct icon */
|
|
|
|
uint8_t icon[0x300];
|
|
|
|
|
|
|
|
/* unknown stuff */
|
|
|
|
uint8_t _unknown5[0x90C];
|
|
|
|
|
|
|
|
/* language name (null terminated?) */
|
|
|
|
uint8_t language_name[16];
|
|
|
|
|
|
|
|
/* language salutation (null terminated?) */
|
|
|
|
uint8_t language_salutation[16];
|
|
|
|
|
|
|
|
/* filename (extension included) */
|
|
|
|
uint8_t filename[0x144];
|
|
|
|
};
|
|
|
|
|
|
|
|
/* And here is the Classpad-specific subheader: */
|
|
|
|
|
|
|
|
struct _classpad_subheader {
|
|
|
|
/* unknown */
|
|
|
|
uint8_t _unknown4[0x46];
|
|
|
|
|
|
|
|
/* the C1A filename */
|
|
|
|
uint8_t filename[0x144];
|
|
|
|
|
|
|
|
/* unknown */
|
|
|
|
uint8_t _unknown5[0x2C];
|
|
|
|
|
|
|
|
/* icon (maybe 46x30 pixels? packed 1-bit) */
|
|
|
|
uint8_t icon[172];
|
|
|
|
|
|
|
|
/* unknown */
|
|
|
|
uint8_t _unknown3[0xC54];
|
|
|
|
};
|
|
|
|
|
2017-03-18 08:39:47 +01:00
|
|
|
/* Also, if the platform is the Prizm, there is a footer at the end of the
|
2017-03-17 22:23:55 +01:00
|
|
|
* file, which is only made of a 32-bit checksum that should be equal to
|
|
|
|
* the subheader checksum.
|
|
|
|
*
|
2017-03-21 02:10:01 +01:00
|
|
|
* Picture formats (C2P, G3P) have a common picture standard subheader, which
|
|
|
|
* is the following: */
|
|
|
|
|
|
|
|
struct standard_picheader {
|
|
|
|
/* magic sequence: "CC" for the Classpad, "CP" for the Prizm */
|
|
|
|
uint8_t cp[2];
|
|
|
|
|
|
|
|
/* "0100", either in raw (0x00, 0x01) for G3P
|
|
|
|
* or in ASCII (0x30, 0x31) for C2P */
|
|
|
|
uint8_t magic[4];
|
|
|
|
|
|
|
|
/* magic sequences:
|
|
|
|
* - "ColorCP\0" for the C2P;
|
|
|
|
* - "LY755\0\0\0" for the G3P. */
|
|
|
|
uint8_t magic2[8];
|
|
|
|
|
|
|
|
/* unknown byte: 0x02 on the G3P, 0x00 on the C2P */
|
|
|
|
uint8_t _unknown0;
|
|
|
|
|
|
|
|
/* unused byte */
|
|
|
|
uint8_t _unused;
|
|
|
|
|
|
|
|
/* filesize after the StandardHeader */
|
|
|
|
uint32_t filesize;
|
|
|
|
|
|
|
|
/* "Always contains the 32-bit big-endian integer 0x00000001" */
|
|
|
|
uint32_t _alwaysone;
|
|
|
|
|
|
|
|
/* subsize (what's after the standard picture header) */
|
|
|
|
uint32_t subsize;
|
|
|
|
|
|
|
|
/* unknown gap */
|
|
|
|
uint8_t _unknown2[0x7C];
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Then we have the specific header -- see `libg1m/format/std/picture.h`.
|
|
|
|
*
|
|
|
|
* Where do you want to go next? Pick your poison. */
|
2017-02-28 17:08:52 +01:00
|
|
|
|
|
|
|
# pragma pack()
|
|
|
|
# include <libg1m/format/std/addin.h>
|
|
|
|
# include <libg1m/format/std/eact.h>
|
|
|
|
# include <libg1m/format/std/mcs.h>
|
|
|
|
# include <libg1m/format/std/storage.h>
|
|
|
|
# include <libg1m/format/std/picture.h>
|
|
|
|
# include <libg1m/format/std/lang.h>
|
|
|
|
# include <libg1m/format/std/fkey.h>
|
|
|
|
#endif /* LIBG1M_FORMAT_STD_H */
|