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/mcs.h

180 lines
5.1 KiB
C

/* ************************************************************************** */
/* _____ _ */
/* libg1m/format/mcs.h |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/11/02 14:15:46 |___/ */
/* */
/* ************************************************************************** */
#ifndef LIBG1M_FORMAT_MCS_H
# define LIBG1M_FORMAT_MCS_H
# include <libg1m.h>
# include <stdint.h>
# pragma pack(1)
/* MCS is the main filesystem on CASIO calculators. They contain settings,
* programs, lists, pictures, captures, matrixes, and other data CASIO
* calculators own.
*
* Keep in mind that all numbers in the MCS format are BCD-encoded.
* Because of some precision issue, we'll deliver them to the user as is.
*
* So now we are not restricted to one part. Remember the `number` field in
* the Standard Header? We once thought it was the number of parts to come.
* But no. In general, we have one subpart per part, but in some case, we
* have more, like for the LISTFILEs. And that is how we realized the `number`
* in the Standard Header wasn't the number of parts, but the total number
* of subparts.
*
* Each part have a header, and here it is: */
struct mcs_subheader {
/* main ID ("PROGRAM", zero padded) */
uint8_t intname[16];
/* subitem count: haha, read what follows! */
uint32_t subcount;
};
/* Because yes, an part of an MCS G1M file has subparts!
* Each one of them represent a single file in the MCS.
* According to their type, they are in different directories: */
enum mcs_filetype {
mcs_ftype_program = 0x1,
mcs_ftype_list = 0x5,
mcs_ftype_mat = 0x6,
mcs_ftype_picture = 0x7,
mcs_ftype_capture = 0xa,
mcs_ftype_spreadsheet = 0xfe,
};
/* And they also have a directory name, which is less precise. Why?
* We don't know! That's the main thing with reverse engineering.
*
* For basic programs, it is: */
# define DIRNAME_PROGRAM "system"
/* For most alpha-mem elements (list, matrixes, pictures): */
# define DIRNAME_ALPHAMEM "main"
/* And for captures: */
# define DIRNAME_CAPTURE "@REV2"
/* Now all of this is said, each part has this header: */
struct mcs_fileheader {
/* the directory name (zero-padded).*/
uint8_t dirname[8];
/* the file name (item name) */
uint8_t filename[8];
/* the file type. */
uint8_t filetype;
/* the size of the part data, without the part header. */
uint32_t datalength;
/* some alignment */
uint8_t align[3];
};
/* Beneath that, we have specific subsubheaders for specific types.
* Here's what it is for programs: */
struct mcs_programheader {
/* the program password. not encrypted, anything */
uint8_t password[8];
/* and some alignment. */
uint8_t align[2];
};
/* And, well, spreadsheets are more complicated than that.
* There is a header, a column directory and a column definition table.
*
* The header mainly contains the column count: */
struct mcs_spreadsheetheader {
/* magic number? */
uint8_t magic;
/* column count (max: 26), on 24 bits and non-aligned */
uint32_t column_count : 24;
/* alignment or magic? {0, 0, 0, 0} */
uint8_t align[4];
/* number of column definitions */
uint32_t defs_size;
/* alignment or magic II? {0, 0, 0, 0} */
uint8_t align2[4];
};
/* The column definition table is the main definition. It contains the row
* directory, which is a 80-bytes long bitfield indicating if cells are empty
* or not, and the list of non-empty cells.
*
* Each cell is a BCD structure.
*
* The column directory is just a list of 4-bytes sizes of each column,
* counting the row directory and the cells. It's easier to naviguate to
* a column quicker.
*
* Now, what about captures? Well, their header is the following: */
struct mcs_captureheader {
/* the width (0x80) */
uint16_t width;
/* the height (0x40) */
uint16_t height;
};
/* Then the image follows (0x400 for a 0x80*0x40px image).
* A picture is the same that an capture, but without the header and containing
* two 128x64 images (0x800 bytes).
*
* Lists! (had no idea how to introduce them)
* After their header, they have `element_count` BCD list corresponding
* to the numbers real part.
* If at least one of the elements have an imaginary part, there is another
* list right behind of `element_count` BCDs, with all of the imaginary
* parts.
*
* Here's their header: */
struct mcs_listheader {
/* probably the title */
uint8_t title[8];
/* the elements count */
uint16_t element_count;
/* undocumented (always 0?) */
uint8_t undocumented[5];
/* undocumented (either 0x00 or 0x4F) */
uint8_t undocumented2;
};
/* Now, let's see matrixes! */
struct mcs_matheader {
/* undocumented */
uint8_t undocumented[8];
/* height */
uint16_t height;
/* width */
uint16_t width;
/* re-undocumented */
uint8_t undocumented2[4];
};
# pragma pack()
#endif /* LIBG1M_FORMAT_MCS_H */