/* ***************************************************************************** * libg1m/format.h -- the G1M format 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_H # define LIBG1M_FORMAT_H # include # pragma pack(1) /* Welcome on this new episode of Monster Circus! Today we'll present to you * something that you might not be able to forget: the G1M format. * * 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`. */ # pragma pack() /* After the Standard Header is read and the type is read, we have parts, * each with their own subheaders and their own subtilities. * * Where do you want to start? Pick your poison. */ # include # include # include # include # include # include # include #endif /* LIBG1M_FORMAT_H */