cake
/
libg1m
Archived
1
0
Fork 0
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libg1m/include/libg1m/format/std.h

250 lines
6.6 KiB
C

/* *****************************************************************************
* 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.
*
* 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:
* - 0x00: picture;
* - 0x01: add-in;
* - 0x02: function keys;
* - 0x04: language files; */
uint8_t filetype;
/* platform:
* - 0x00: fx-CP;
* - 0x01: Prizm */
uint8_t platform;
/* unknown */
uint8_t _unknown0[4];
/* size of the data + footer? */
uint32_t df_size;
/* 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];
};
/* 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.
*
* 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. */
# 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 */