cake
/
libg1m
Archived
1
0
Fork 0

Namespace for format headers.

This commit is contained in:
Thomas Touhey 2017-04-13 16:26:22 +02:00
parent 264e8d5f66
commit 0db29bafb3
39 changed files with 717 additions and 663 deletions

View File

@ -60,14 +60,14 @@
*
* The header format is the following: */
struct cas40 {
uint8_t data[2]; /* data type -- see `type/cas.c`. */
uint8_t misc[5]; /* type-specific subheader */
uint8_t filename[12]; /* editor filename. */
uint8_t password[12]; /* editor password. */
uint8_t _reserved[7]; /* 0xFFs */
uint8_t checksum;
};
typedef struct g1m_cas40_s {
uint8_t g1m_cas40_data[2]; /* data type -- see `type/cas.c`. */
uint8_t g1m_cas40_misc[5]; /* type-specific subheader */
uint8_t g1m_cas40_filename[12]; /* editor filename. */
uint8_t g1m_cas40_password[12]; /* editor password. */
uint8_t g1m_cas40__reserved0[7]; /* 0xFFs */
uint8_t g1m_cas40_checksum;
} g1m_cas40_t;
/* The specific bytes are different according to the datatype, but its
* length is fixed. */
@ -86,46 +86,48 @@ struct cas40 {
* was always 0x31 ('1' in ASCII), which are 40 bytes long. From there and other
* pieces of documentation, here are the extension types I could find: */
# define casdyn_ext_9850 0x00 /* 50 bytes long */
# define casdyn_ext_end 0xFF /* yet an alias to `casdyn_ext_9850`,
* used by the END packet. */
# define casdyn_ext_g100 0x31 /* 40 bytes long */
# define casdyn_ext_g100b 0x32 /* yet an alias to `casdyn_ext_g100`,
* used for some commands */
# define g1m_casdyn_ext_9850 0x00 /* 50 bytes long */
# define g1m_casdyn_ext_end 0xFF /* yet an alias to `casdyn_ext_9850`,
* used by the END packet. */
# define g1m_casdyn_ext_g100 0x31 /* 40 bytes long */
# define g1m_casdyn_ext_g100b 0x32 /* yet an alias to `casdyn_ext_g100`,
* used for some commands */
/* Here are the common fields to all packets: */
struct casdyn {
typedef struct g1m_casdyn_s {
/* app */
uint8_t app[3];
uint8_t g1m_casdyn_app[3];
/* type of extension - see the `casdyn_ext_*` macros above */
uint8_t ext;
};
uint8_t g1m_casdyn_ext;
} g1m_casdyn_t;
/* The format the CFX-9850G uses is 50 bytes long, so we'll name it CAS50.
* Here is the header format after the CASDYN header is read: */
struct _cas50 {
typedef struct g1m_cas50_s {
/* types */
uint8_t data[2];
uint8_t g1m_cas50_data[2];
/* data length */
uint16_t width, height;
uint8_t name[8];
uint16_t g1m_cas50_width;
uint16_t g1m_cas50_height;
uint8_t g1m_cas50_name[8];
/* variable-related data */
uint8_t prefix[8]; /* "Variable" for vars, "PROG\x99" "0\xFF\xFF" for progs,
* 0xFFs otherwise */
uint8_t aux[8]; /* variable: "R\x0A"/"C\x0A", editor: password */
uint8_t g1m_cas50_prefix[8]; /* "Variable" for vars,
* "PROG\x99" "0\xFF\xFF" for progs,
* 0xFFs otherwise */
uint8_t g1m_cas50_aux[8]; /* variable: "R\x0A"/"C\x0A", editor: password */
/* something else (?) */
uint8_t nl[2]; /* 'NL'? "\xFF\xFF" for progs */
uint8_t _reserved[12];
uint8_t g1m_cas50_option1[2]; /* 'NL'? "\xFF\xFF" for progs */
uint8_t g1m_cas50__reserved[12]; /* other options? -> cf. CAT format */
/* end of packet */
uint8_t checksum;
};
uint8_t g1m_cas50_checksum;
} g1m_cas50_t;
/* The format the G100 (AlgebraFX) uses is 40 bytes long, but as CAS40 already
* exists, we'll name this format CAS100 (which is funny because the Graph 100
@ -134,62 +136,63 @@ struct _cas50 {
* Information from here is mainly decoded from Flash100 sources.
* Anyway, here is the CAS100 header after the CASDYN header is read: */
struct _cas100 {
struct g1m_cas100_s {
/* drive?
* - "INF" <1>: system
* - "FR0" <0>: segment
* - "MSG" <1>: language
* - "MR0" <4>: ?
* - "S00" <0>: ? */
uint8_t drive[3];
uint8_t g1m_cas100_drive[3];
/* driver number, in ASCII (0x30 + <num>) */
uint8_t id;
uint8_t g1m_cas100_id;
/* group size (size of each fragment group part to be sent): 1024 */
uint32_t _size;
uint32_t g1m_cas100_size;
/* ExportDrive: 0x80, type? */
uint32_t _type;
uint32_t g1m_cas100_type;
/* drive size: 0x20000 bytes */
uint32_t drive_size;
uint32_t g1m_cas100_drive_size;
/* 0xFFs */
uint8_t _unknown[18];
uint8_t g1m_cas100__unknown[18];
/* checksum */
uint8_t checksum;
uint8_t g1m_cas100_checksum;
};
/* However, the CAS100 header has a variant, with the 'MDL' application: it
* looks like system info. The information here is obtained from Flash100's
* source code, once again. */
struct _cas100_info {
struct g1m_cas100info_s {
/* board identifier? "ZX945" */
uint8_t board[5];
uint8_t _delim0; /* 0xFF */
uint8_t g1m_cas100info_board[5];
uint8_t g1m_cas100info_delim0; /* 0xFF */
/* serial settings? "038400N"
* this would mean 38400 bauds, no parity (2 stop bits?) */
uint8_t settings[11];
uint8_t g1m_cas100info_settings[11];
/* ROM version? "1.00" or "1.01" */
uint8_t version[4];
uint8_t g1m_cas100info_version[4];
/* values? */
uint32_t _val1; /* 0xF00 or 0x1000 */
uint32_t _val2; /* 0x400 */
uint32_t _val3; /* 0x100 */
uint32_t g1m_cas100info__val1; /* 0xF00 or 0x1000 */
uint32_t g1m_cas100info__val2; /* 0x400 */
uint32_t g1m_cas100info__val3; /* 0x100 */
/* hex value with prefix... what? */
uint8_t hex[4]; /* "0x07", litterally, or 0x07 followed by three 0xFFs */
uint8_t _delim1; /* 0xFF */
uint8_t g1m_cas100info_hex[4]; /* "0x07", litterally,
* or 0x07 followed by three 0xFFs */
uint8_t g1m_cas100info_delim1; /* 0xFF */
/* checksum */
uint8_t checksum;
};
uint8_t g1m_cas100info_checksum;
} g1m_cas100info_t;
/* As you can guess, CAS40 and CASDYN are, in theory, incompatible.
* In practice, anyhow, they more or less are: libg1m reads the first 4 bytes

View File

@ -27,13 +27,13 @@
*
* It starts with 20 graph entries, which have this format: */
struct cas_gmem_entry {
typedef struct g1m_cas_gmem_entry_s {
/* function type code */
uint8_t type;
uint8_t g1m_cas_gmem_entry_type;
/* flags */
uint8_t flags;
};
uint8_t g1m_cas_gmem_entry_flags;
} g1m_cas_gmem_entry_t;
/* Where the function types are the following: */

View File

@ -26,11 +26,11 @@
/* ************************************************************************** */
/* In old CAS headers, the five specific bytes are the following: */
struct cas_spe_screenshot {
uint8_t height;
uint8_t width;
uint8_t _unused[3];
};
typedef struct g1m_cas_spe_screenshot_s {
uint8_t g1m_cas_spe_screenshot_height;
uint8_t g1m_cas_spe_screenshot_width;
uint8_t g1m_cas_spe_screenshot__unused[3];
} g1m_cas_spe_screenshot_t;
/* The specific bytes for a number start with either "RA" or "CA", 'R' or 'C'
* meaning the number is complex or not. */

View File

@ -31,12 +31,12 @@
# define casiolink_program_basen 0x40 /* base-n mode */
# define casiolink_program_drawst 0x80 /* draw stats graph */
struct cas_spe_program {
uint8_t _unknown;
uint16_t length;
uint8_t flags;
uint8_t _unknown2;
};
typedef struct g1m_cas_spe_program_s {
uint8_t g1m_cas_spe_program__unknown0;
uint16_t g1m_cas_spe_program_length;
uint8_t g1m_cas_spe_program_flags;
uint8_t g1m_cas_spe_program__unknown1;
} g1m_cas_spe_program_t;
/* Then the program, using the multi-byte FONTCHARACTER encoding, comes.
* F-MEM (saves of series of commands) are stored like very small programs. */

View File

@ -26,16 +26,16 @@
* optional compiled part. One thing to know is that every specific header has
* an internal header, which always has this structure: */
struct casemul_internal_header {
typedef struct g1m_casemul_intheader_s {
/* this signature, a set of 4 characters identifying the header type */
uint32_t signature;
uint32_t g1m_casemul_intheader_signature;
/* version (more or less 0xMMmm, where MM is the major and mm the minor) */
uint32_t version;
uint32_t g1m_casemul_intheader_version;
/* header size */
uint32_t size;
};
uint32_t g1m_casemul_intheader_size;
} g1m_casemul_intheader_t;
/* The signature is made using `MAKELONG`, a Microsoft Windows specific macro
* which concatenates two words (16-bit integers) into a single long
@ -69,19 +69,19 @@ struct casemul_internal_header {
* The expected version is 1.00. */
# define casemul_compiled 0x80 /* if the compiled program is there */
struct casemul_header {
typedef struct g1m_casemul_header_s {
/* the flags */
uint8_t flags;
uint8_t g1m_casemul_header_flags;
/* offset of the sources */
uint32_t source_offset;
uint32_t g1m_casemul_header_source_offset;
/* compiled program offset */
uint32_t compiled_offset;
uint32_t g1m_casemul_header_compiled_offset;
/* some alignment? */
uint8_t _align[3];
};
uint8_t g1m_casemul_header__align[3];
} g1m_casemul_header_t;
/* At the beginning of the source part, we find the source header.
* The source part contains the programs, pictures, matrixes and lists as four
@ -90,37 +90,37 @@ struct casemul_header {
* Its internal header ID is "SRCE" (RSEC).
* The expected version is 1.00. */
struct casemul_source_header {
typedef struct g1m_casemul_source_header_s {
/* number of program records in the program block */
uint8_t programs;
uint8_t g1m_casemul_source_header_programs;
/* number of picture records in the program block */
uint8_t pictures;
uint8_t g1m_casemul_source_header_pictures;
/* number of matrix records in the program block */
uint8_t matrixes;
uint8_t g1m_casemul_source_header_matrixes;
/* number of list records in the list block */
uint8_t lists;
uint8_t g1m_casemul_source_header_lists;
/* program block offset */
uint32_t programs_offset;
uint32_t g1m_casemul_source_header_programs_offset;
/* picture block offset (length of the file before) */
uint32_t pictures_offset;
uint32_t g1m_casemul_source_header_pictures_offset;
/* matrix block offset */
uint32_t matrixes_offset;
uint32_t g1m_casemul_source_header_matrixes_offset;
/* list block offset */
uint32_t list_offset;
uint32_t g1m_casemul_source_header_list_offset;
/* main program ID */
uint8_t program_id;
uint8_t g1m_casemul_source_header_program_id;
/* alignment */
uint8_t _align[3];
};
uint8_t g1m_casemul_source_header__align[3];
} g1m_casemul_source_header_t;
/* At the beginning of the compiled part, we find the compiled header.
* The compilation process is unknown (yet to read the sources to find out
@ -129,11 +129,10 @@ struct casemul_source_header {
* Its internal header ID is "COMP" (OCPM).
* The expected version is 1.00. */
struct casemul_comp_header {
typedef struct g1m_casemul_compiled_header_s {
/* the number of instructions (size of the part) */
uint32_t instructions_count;
};
uint32_t g1m_casemul_compiled_header_size;
} g1m_casemul_compiled_header_t;
/* ************************************************************************** */
/* Record */
/* ************************************************************************** */
@ -158,10 +157,10 @@ struct casemul_comp_header {
/* ************************************************************************** */
/* A program has type "PROG" (RPGO). Its subheader is the following: */
struct casemul_prog_header {
typedef struct g1m_casemul_prog_header_s {
/* program length after Casemul encoding */
uint32_t length;
};
uint32_t g1m_casemul_prog_header_length;
} g1m_casemul_prog_header_t;
/* Casemul makes use of tokens instead of FONTCHARACTERs or Unicode - this
* should be documented in the FONTCHARACTER reference. */
@ -170,13 +169,14 @@ struct casemul_prog_header {
/* ************************************************************************** */
/* A picture has type "PICT" (IPTC), and has the following subheader: */
struct casemul_pict_header {
typedef struct g1m_casemul_pict_header_s {
/* size */
uint8_t width, height;
uint8_t g1m_casemul_pict_header_width;
uint8_t g1m_casemul_pict_header_height;
/* ... aaaaand alignment. (you know, unchecked theory?) */
uint8_t _align[2];
};
uint8_t g1m_casemul_pict_header__align[2];
} g1m_casemul_pict_header_t;
/* Also, pixels are organized per _column_; this comes from the original code:
*
@ -191,11 +191,12 @@ struct casemul_pict_header {
/* A matrix has type "MTRX" (TMXR) and its its subheader has the following
* structure: */
struct casemul_mtrx_header {
typedef struct g1m_casemul_mtrx_header_s {
/* number of lines and columns
* actually int-s in the original code... */
uint32_t lines, columns;
};
uint32_t g1m_casemul_mtrx_header_lines;
uint32_t g1m_casemul_mtrx_header_columns;
} g1m_casemul_mtrx_header_t;
/* Then it's simply a tab of `lines*columns` `double` numbers,
* ordered by lines (y). They are the real parts, as the numbers in those
@ -205,11 +206,11 @@ struct casemul_mtrx_header {
/* ************************************************************************** */
/* A list has type "LIST" (ILTS) and has the following subheader structure: */
struct casemul_list_header {
typedef struct g1m_casemul_list_header_s {
/* number of lines
* actually int-s in the original code... */
uint32_t lines;
};
uint32_t g1m_casemul_list_header_lines;
} g1m_casemul_list_header_t;
/* Then it's simply a tab of `lines` `double` numbers.
* The numbers in these have no imaginary parts. */

View File

@ -26,7 +26,7 @@
*
* Once the format is deobfuscated, this is the header structure: */
struct fxi_header {
typedef struct g1m_fxi_header_s {
/* unknown - probably part of the magic? "\xD5\xD7\x1F" "f" */
uint8_t _unknown[4];
@ -51,11 +51,11 @@ struct fxi_header {
/* introduction? */
uint8_t type[11];
};
} g1m_fxi_header_t;
/* Then come the meta-entries, which have this structure: */
struct fxi_entry {
typedef struct g1m_fxi_entry_s {
/* entry type: first type is 'NP', then {0x01, 0x80}. */
uint8_t type[2];
uint8_t _unused[2];
@ -85,7 +85,7 @@ struct fxi_entry {
/* TODO: finish me */
};
} g1m_fxi_entry_t;
# pragma pack()
#endif

View File

@ -28,22 +28,22 @@
*
* They have this header: */
struct mcs_cellsheader {
typedef struct g1m_mcs_cellsheader_s {
/* undocumented: probably the title? */
uint8_t title[8];
uint8_t g1m_mcs_cellsheader_title[8];
/* height */
uint16_t height;
uint16_t g1m_mcs_cellsheader_height;
/* width */
uint16_t width;
uint16_t g1m_mcs_cellsheader_width;
/* re-undocumented */
uint8_t _undocumented[3];
uint8_t g1m_mcs_cellsheader__undocumented[3];
/* undocumented byte (either 0x00 or 0x4F) */
uint8_t _unknown;
};
uint8_t g1m_mcs_cellsheader__unknown;
} g1m_mcs_cellsheader_t;
/* Then we have width*height BCD cells, which corresponds to the real parts,
* grouped by height.

View File

@ -23,13 +23,13 @@
/* Captures start with a simple header: */
struct mcs_captureheader {
typedef struct g1m_mcs_captureheader_s {
/* the width (0x80) */
uint16_t width;
uint16_t g1m_mcs_captureheader_width;
/* the height (0x40) */
uint16_t height;
};
uint16_t g1m_mcs_captureheader_height;
} g1m_mcs_captureheader_t;
/* Then the image follows (0x400 for a 0x80*0x40px image).
* A picture is the same that an capture, but without the header and containing

View File

@ -24,13 +24,13 @@
/* Programs have a simple header: */
struct mcs_programheader {
typedef struct g1m_mcs_programheader_s {
/* the program password. not encrypted, anything */
uint8_t password[8];
uint8_t g1m_mcs_programheader_password[8];
/* and some alignment. */
uint8_t align[2];
};
uint8_t g1m_mcs_programheader__align[2];
} g1m_mcs_programheader_t;
/* Then comes their content, multi-byte FONTCHARACTER encoded. */

View File

@ -26,29 +26,29 @@
*
* For normal ones, there is a header: */
struct mcs_spreadsheetheader {
typedef struct g1m_mcs_spreadsheet_header_s {
/* has subheader: 0x01 if yes */
uint8_t has_subheader;
uint8_t g1m_mcs_spreadsheet_header_has_subheader;
/* column count (max: 26), on 24 bits and non-aligned */
uint32_t column_count : 24;
};
uint32_t g1m_mcs_spreadsheet_header_column_count :24;
} g1m_mcs_spreadsheet_header_t;
/* Then, if it is a normal spreadsheet, there is a subheader,
* a column directory and a column definition table.
*
* Here's the subheader: */
struct mcs_spreadsheet_subheader {
typedef struct g1m_mcs_spreadsheet_subheader_s {
/* alignment or magic? {0, 0, 0, 0} */
uint8_t align[4];
uint8_t g1m_mcs_spreadsheet_subheader__align0[4];
/* number of column definitions */
uint32_t defs_size;
uint32_t g1m_mcs_spreadsheet_subheader_defs_size;
/* alignment or magic II? {0, 0, 0, 0} */
uint8_t align2[4];
};
uint8_t g1m_mcs_spreadsheet_subheader__align1[4];
} g1m_mcs_spreadsheet_subheader_t;
/* 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

View File

@ -42,35 +42,35 @@
* 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 {
typedef struct g1m_standard_header_s {
/* the file identifier */
uint8_t main_id[8];
uint8_t g1m_standard_header_main_id[8];
/* our subtype! */
uint8_t subtype[6];
uint8_t g1m_standard_header_subtype[6];
/* first control byte: filesize LSB + 0x41 */
uint8_t control;
uint8_t g1m_standard_header_control;
/* said to be 0x01, but doesn't need to */
uint8_t align_one;
uint8_t g1m_standard_header_align_one;
/* total filesize */
uint32_t filesize;
uint32_t g1m_standard_header_filesize;
/* second control byte: filesize LSB + 0xb8 */
uint8_t control2;
uint8_t g1m_standard_header_control2;
/* alignment */
uint8_t align[7];
uint8_t g1m_standard_header__align[7];
/* is obfuscated - useful for G3P */
uint8_t obfuscated0;
uint8_t obfuscated1;
uint8_t g1m_standard_header_obfuscated0;
uint8_t g1m_standard_header_obfuscated1;
/* number of objects contained (useful for MCS filetype) */
uint16_t number;
};
uint16_t g1m_standard_header_number;
} g1m_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:
@ -92,113 +92,113 @@ struct standard_header {
* 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 {
typedef struct g1m_standard_subheader_s {
/* checksum */
uint32_t checksum;
uint32_t g1m_standard_subheader_checksum;
/* file type:
* - 0x00: picture (not used with this header);
* - 0x01: add-in;
* - 0x02: function keys;
* - 0x04: language files; */
uint8_t filetype;
uint8_t g1m_standard_subheader_filetype;
/* platform:
* - 0x00: fx-CP;
* - 0x01: Prizm */
uint8_t platform;
uint8_t g1m_standard_subheader_platform;
/* unknown */
uint8_t _unknown0[4];
uint8_t g1m_standard_subheader__unknown0[4];
/* size of the data + footer? */
uint32_t df_size;
uint32_t g1m_standard_subheader_df_size;
/* control:
* - for a G3A: filesize - 0x7000 - 4
* - for a C1A: filesize - 0x1000 - 4 */
uint32_t control;
uint32_t g1m_standard_subheader_control;
/* unknown */
uint8_t _unknown1[4];
uint8_t g1m_standard_subheader__unknown1[4];
/* message zone size - unreliable (valid could have zero) */
uint32_t message_zone_size;
uint32_t g1m_standard_subheader_message_zone_size;
/* model; for C1A : GY437 */
uint8_t models[6];
/* model; for C1A: GY437 */
uint8_t g1m_standard_subheader_models[6];
/* title/language name */
uint8_t title[28];
uint8_t g1m_standard_subheader_title[28];
/* filesize */
uint32_t filesize;
uint32_t g1m_standard_subheader_filesize;
/* internal name */
uint8_t internal_name[11];
uint8_t g1m_standard_subheader_internal_name[11];
/* language labels */
uint8_t labels[8][24];
uint8_t g1m_standard_subheader_labels[8][24];
/* eAct strip flag (0x00: can't be used, 0x01: can be used) */
uint8_t eact_strip_flag;
uint8_t g1m_standard_subheader_eact_strip_flag;
/* unknown */
uint8_t _unknown2[4];
uint8_t g1m_standard_subheader__unknown2[4];
/* version: MM.mm.ffff */
uint8_t version[10];
uint8_t g1m_standard_subheader_version[10];
/* unknown */
uint8_t _unknown3[2];
uint8_t g1m_standard_subheader__unknown3[2];
/* timestamp: YYYY.MMDD.HHmm */
uint8_t timestamp[14];
};
uint8_t g1m_standard_subheader_timestamp[14];
} g1m_standard_subheader_t;
/* Here is the Prizm-specific subheader: */
struct _prizm_subheader {
typedef struct g1m_standard_prizm_subheader_s {
/* unknown */
uint8_t _unknown4[38];
uint8_t g1m_standard_prizm_subheader__unknown0[38];
/* eAct strip labels */
uint8_t eact_strip_labels[8][36];
uint8_t g1m_standard_prizm_subheader_eact_strip_labels[8][36];
/* eAct icon */
uint8_t icon[0x300];
uint8_t g1m_standard_prizm_subheader_icon[0x300];
/* unknown stuff */
uint8_t _unknown5[0x90C];
uint8_t g1m_standard_prizm_subheader__unknown1[0x90C];
/* language name (null terminated?) */
uint8_t language_name[16];
uint8_t g1m_standard_prizm_subheader_language_name[16];
/* language salutation (null terminated?) */
uint8_t language_salutation[16];
uint8_t g1m_standard_prizm_subheader_language_salutation[16];
/* filename (extension included) */
uint8_t filename[0x144];
};
uint8_t g1m_standard_prizm_subheader_filename[0x144];
} g1m_standard_prizm_subheader_t;
/* And here is the Classpad-specific subheader: */
struct _classpad_subheader {
typedef struct g1m_standard_classpad_subheader_s {
/* unknown */
uint8_t _unknown4[0x46];
uint8_t g1m_standard_classpad_subheader__unknown0[0x46];
/* the C1A filename */
uint8_t filename[0x144];
uint8_t g1m_standard_classpad_subheader_filename[0x144];
/* unknown */
uint8_t _unknown5[0x2C];
uint8_t g1m_standard_classpad_subheader__unknown1[0x2C];
/* icon (maybe 46x30 pixels? packed 1-bit) */
uint8_t icon[172];
uint8_t g1m_standard_classpad_subheader_icon[172];
/* unknown */
uint8_t _unknown3[0xC54];
};
uint8_t g1m_standard_classpad_subheader__unknown2[0xC54];
} g1m_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
@ -209,37 +209,37 @@ struct _classpad_subheader {
/* Picture formats (C2P, G3P) have a common picture standard subheader, which
* is the following: */
struct standard_picheader {
typedef struct g1m_standard_picheader_s {
/* magic sequence: "CC" for the Classpad, "CP" for the Prizm */
uint8_t cp[2];
uint8_t g1m_standard_picheader_cp[2];
/* "0100", either in raw (0x00, 0x01) for G3P
* or in ASCII (0x30, 0x31) for C2P */
uint8_t magic[4];
uint8_t g1m_standard_picheader_magic[4];
/* magic sequences:
* - "ColorCP\0" for the C2P;
* - "LY755\0\0\0" for the G3P. */
uint8_t magic2[8];
uint8_t g1m_standard_picheader_magic2[8];
/* unknown byte: 0x02 on the G3P, 0x00 on the C2P */
uint8_t _unknown0;
uint8_t g1m_standard_picheader__unknown0;
/* unused byte */
uint8_t _unused;
uint8_t g1m_standard_picheader__unused;
/* filesize after the StandardHeader */
uint32_t filesize;
uint32_t g1m_standard_picheader_filesize;
/* "Always contains the 32-bit big-endian integer 0x00000001" */
uint32_t _alwaysone;
uint32_t g1m_standard_picheader__alwaysone;
/* subsize (what's after the standard picture header) */
uint32_t subsize;
uint32_t g1m_standard_picheader_subsize;
/* unknown gap */
uint8_t _unknown2[0x7C];
};
uint8_t g1m_standard_picheader__unknown2[0x7C];
} g1m_standard_picheader_t;
/* Then we have the specific header -- see `libg1m/format/std/picture.h`. */
/* ************************************************************************** */

View File

@ -30,51 +30,51 @@
# define G1A_ICON_WIDTH 30
# define G1A_ICON_HEIGHT 17
struct g1a_subheader {
typedef struct g1m_addin_subheader_s {
/* the internal name, of format "@APPNAME".
* useful for add-ins calling themselves... I guess? */
uint8_t internal_name[8];
uint8_t g1m_addin_subheader_internal_name[8];
/* spacing */
uint8_t _spacing[3];
uint8_t g1m_addin_subheader__spacing0[3];
/* the number of estrips (I don't know yet) */
uint8_t estrips_count;
uint8_t g1m_addin_subheader_estrips_count;
/* spacing */
uint8_t _spacing2[4];
uint8_t g1m_addin_subheader__spacing1[4];
/* the add-in version, of format "01.23.4567"
* the "01.23" will be displayed in SYSTEM > VERSION */
uint8_t version[10];
uint8_t g1m_addin_subheader_version[10];
/* spacing */
uint8_t _spacing3[2];
uint8_t g1m_addin_subheader__spacing2[2];
/* the add-in creation type, of format "YYYY.MMDD.HHMM" */
uint8_t creation_date[14];
uint8_t g1m_addin_subheader_creation_date[14];
/* spacing */
uint8_t _spacing4[2];
uint8_t g1m_addin_subheader__spacing3[2];
/* 30x17 pixel menu icon bitmap */
uint8_t icon[68];
uint8_t g1m_addin_subheader_icon[68];
/* spacing */
uint8_t _spacing5[0x144];
uint8_t g1m_addin_subheader__spacing4[0x144];
/* program title */
uint8_t title[8];
uint8_t g1m_addin_subheader_title[8];
/* spacing */
uint8_t _spacing6[0x14];
uint8_t g1m_addin_subheader__spacing5[0x14];
/* and the filesize of the part! */
uint32_t filesize;
uint32_t g1m_addin_subheader_filesize;
/* spacing */
uint8_t _spacing7[0xc];
};
uint8_t g1m_addin_subheader__spacing6[0xc];
} g1m_addin_subheader_t;
/* Then the G1A file will just contain the add-in code and stop. */
/* ************************************************************************** */
@ -88,26 +88,26 @@ struct g1a_subheader {
# define G3A_ICON_WIDTH 92
# define G3A_ICON_HEIGHT 64
struct g3a_subheader {
typedef struct g1m_prizm_addin_subheader_s {
/* selected and unselected icon image */
uint8_t selected_icon_image[0x3000];
uint8_t unselected_icon_image[0x3000];
};
uint8_t g1m_prizm_addin_subheader_selected_icon_image[0x3000];
uint8_t g1m_prizm_addin_subheader_unselected_icon_image[0x3000];
} g1m_prizm_addin_subheader_t;
/* And the C1A subheader goes like this: */
# define C1A_ICON_WIDTH 46
# define C1A_ICON_HEIGHT 30
struct c1a_subheader {
typedef struct g1m_classpad_addin_subheader_s {
/* unknown bytes */
uint8_t _unknown2[0x2C];
uint8_t g1m_classpad_addin_subheader__unknown0[0x2C];
/* this is an approximation (46x30 pixels, packed 1-bit) */
uint8_t icon[172];
uint8_t g1m_classpad_addin_subheader_icon[172];
/* unknown */
uint8_t _unknown3[0xC54];
};
uint8_t g1m_classpad_addin_subheader__unknown1[0xC54];
} g1m_classpad_addin_subheader_t;
# pragma pack()
#endif /* LIBG1M_FORMAT_STD_ADDIN_H */

View File

@ -46,83 +46,72 @@
*
* So the main header is: */
struct eact_header {
typedef struct g1m_eact_header_s {
/* the filesize */
uint32_t filesize;
uint32_t g1m_eact_header_filesize;
/* the size of the setup area */
uint32_t setup_area_size;
uint32_t g1m_eact_header_setup_area_size;
/* the E-Act version */
uint32_t eact_version;
uint32_t g1m_eact_header_eact_version;
/* The OS version - only with G2E/G3E */
uint32_t os_version;
};
uint32_t g1m_eact_header_os_version;
} g1m_eact_header_t;
/* And now, the funniest part: the content.
* So a content has this header: */
struct eact_contentheader {
typedef struct g1m_eact_content_header_s {
/* content type: @EACT, @RUNMAT, ... */
uint8_t type[8];
uint8_t g1m_eact_content_header_type[8];
/* align for element name */
uint8_t align[8];
uint8_t g1m_eact_content_header__align0[8];
/* element name: "EACT1", "TEXT1", ... */
uint8_t name[16];
uint8_t g1m_eact_content_header_name[16];
/* align for subheader */
uint8_t align2[4];
};
uint8_t g1m_eact_content_header__align1[4];
} g1m_eact_content_header_t;
/* There are several types of contents.
* The most basic one is also called "@EACT".
* It has this content subheader: */
struct eact_eactheader {
typedef struct g1m_eact_content_eact_header_s {
/* line count */
uint32_t line_count;
};
uint32_t g1m_eact_content_eact_header_line_count;
} g1m_eact_content_eact_header_t;
/* And after, lines come. First of all, there is a line descriptor table,
* that contain the line type and the line offset from the subheader begin.
* A line type can have these types: */
enum eact_linetype {
/* contains a calculation */
eact_ltype_calc = 0x03,
/* contains a calculation result (right after the calculation line) */
eact_ltype_calc_result = 0x04,
/* a subcontent, with content header and everything */
eact_ltype_content = 0x06,
/* standard heading - the title surrounded by '=' */
eact_ltype_stdheading = 0x07,
/* a picture - the content is the path to the picture
* ex: '\\fls0\Pict\Pict01.g3p' (With CASIO's encoding on 16-bits) */
eact_ltype_picture = 0x08,
/* Some pure text */
eact_ltype_text = 0x81,
/* Text mixed up with functions -- described by SimLo, untested here */
eact_ltype_code = 0x82
};
typedef int g1m_eact_ltype_t;
# define g1m_eact_ltype_calc 0x03 /* calculation */
# define g1m_eact_ltype_calc_result 0x04 /* calculation result
* usually right after a calculation */
# define g1m_eact_ltype_content 0x06 /* subcontent */
# define g1m_eact_ltype_stdheading 0x07 /* standard heading
* title is surrounded by '=' */
# define g1m_eact_ltype_picture 0x08 /* path to a picture
* e.g. '\\fls0\Pict\Pict01.g3p'
* (fixed-width FONTCHARACTER)*/
# define g1m_eact_ltype_text 0x81 /* pure text */
# define g1m_eact_ltype_code 0x82 /* text mixed up with functions */
/* And here's the line descriptor structure: */
struct line_descriptor {
typedef struct g1m_eact_line_descriptor_s {
/* the entry type */
uint8_t entry_type;
uint8_t g1m_eact_line_descriptor_type;
/* the entry offset */
uint32_t entry_offset :24;
};
uint32_t g1m_eact_line_descriptor_offset :24;
} g1m_eact_line_descriptor_t;
/* And there is only one content after the main header, and it's a content
* of EACT type. But hey, why the heck have we defined several types and stuff?

View File

@ -36,16 +36,16 @@
# define FKEY_WIDTH 24
# define FKEY_HEIGHT 8
struct g1n_subheader {
typedef struct g1m_fkey_subheader_s {
/* usually "PowerUSB" */
uint8_t identifier[8];
uint8_t g1m_fkey_subheader_identifier[8];
/* useless data */
uint8_t _useless[4];
uint8_t g1m_fkey_subheader__useless[4];
/* number of icons */
uint16_t fkey_count;
};
uint16_t g1m_fkey_subheader_count;
} g1m_fkey_subheader_t;
/* Then there is a table of 16-bits offsets (iconXXX - icon0), then the icons.
* The first "icon" is in fact the name of the language. */

View File

@ -26,20 +26,20 @@
/* ************************************************************************** */
/* It all starts with a header: */
struct g1l_subheader {
typedef struct g1m_lang_subheader_s {
/* identifier: is "PowerUSB" on original things */
uint8_t identifier[8];
uint8_t g1m_lang_subheader_identifier[8];
/* OS information (raw binary format), e.g. 0x02,0x09 for 2.09. */
uint8_t os_major;
uint8_t os_minor;
uint8_t g1m_lang_subheader_os_major;
uint8_t g1m_lang_subheader_os_minor;
/* unknown bytes */
uint8_t _unknown[2];
uint8_t g1m_lang_subheader__unknown[2];
/* message count */
uint16_t message_count;
};
uint16_t g1m_lang_subheader_count;
} g1m_lang_subheader_t;
/* Then comes a list of offsets, and the messages.
*
@ -56,22 +56,22 @@ struct g1l_subheader {
* then the Prizm-specific subheader. After this, both the G3L and G3N
* have this language header: */
struct g3l_lang_header {
typedef struct g1m_prizm_lang_subheader_s {
/* sequence: '4C 59 37 35 35 00 00 00' (LY755 ) */
uint8_t sequence[8];
uint8_t g1m_prizm_lang_subheader_sequence[8];
/* unknown: 0x02 */
uint8_t _unknown;
uint8_t g1m_prizm_lang_subheader__unknown;
/* unused byte. */
uint8_t _unused;
uint8_t g1m_prizm_lang_subheader__unused0;
/* number of messages ("possibly 0 base indexed") */
uint32_t num;
uint32_t g1m_prizm_lang_subheader_count;
/* unused bytes */
uint8_t unused2[2];
};
uint8_t g1m_prizm_lang_subheader__unused1[2];
} g1m_prizm_lang_subheader_t;
/* Then we have offsets of all messages (4 bytes each),
* then messages themselves, zero-terminated.

View File

@ -40,33 +40,33 @@
*
* Each group instance have a header, and here it is: */
struct mcs_subheader {
typedef struct g1m_mcs_subheader_s {
/* group name (e.g. "PROGRAM", zero padded) */
uint8_t intname[16];
uint8_t g1m_mcs_subheader_intname[16];
/* subitem count */
uint32_t subcount;
};
uint32_t g1m_mcs_subheader_subcount;
} g1m_mcs_subheader_t;
/* Then follows the files, with their headers and contents.
* And the header iiiiiiis: */
struct mcs_fileheader {
typedef struct g1m_mcs_fileheader_s {
/* the directory name (zero-padded).*/
uint8_t dirname[8];
uint8_t g1m_mcs_fileheader_dirname[8];
/* the file name (item name) */
uint8_t filename[8];
uint8_t g1m_mcs_fileheader_filename[8];
/* the file type. */
uint8_t filetype;
uint8_t g1m_mcs_fileheader_filetype;
/* the size of the part data, without the part header. */
uint32_t datalength;
uint32_t g1m_mcs_fileheader_datalength;
/* some alignment */
uint8_t align[3];
};
uint8_t g1m_mcs_fileheader__align[3];
} g1m_mcs_fileheader_t;
# pragma pack()

View File

@ -37,37 +37,37 @@
/* After the standard headers, comes the specific header: */
struct g3p_subheader {
typedef struct g1m_prizm_picture_subheader_s {
/* magic sequence? is: 0x00, 0x01, 0x00, 0x00 */
uint8_t magic[4];
uint8_t g1m_prizm_picture_subheader_magic[4];
/* size of the image data + footer */
uint32_t df_size;
uint32_t g1m_prizm_picture_subheader_df_size;
/* w0t */
uint8_t _unknown0[2];
uint8_t g1m_prizm_picture_subheader__unknown0[2];
/* width */
uint16_t width;
uint16_t g1m_prizm_picture_subheader_width;
/* height */
uint16_t height;
uint16_t g1m_prizm_picture_subheader_height;
/* color depth - see `g3p_colorsize` */
uint16_t color_depth;
uint16_t g1m_prizm_picture_subheader_color_depth;
/* undocumented, again */
uint8_t _unknown1[4];
uint8_t g1m_prizm_picture_subheader__unknown1[4];
/* length of the image data + 6
* the 6 bytes are:
* - the 16-bit generator ID at the beginning;
* - the 32-bit checksum at the end of the data. */
uint32_t data_size;
uint32_t g1m_prizm_picture_subheader_data_size;
/* Generator ID */
uint16_t generator_id;
};
uint16_t g1m_prizm_picture_subheader_generator_id;
} g1m_prizm_picture_subheader_t;
/* The generator ID is a 16-bit ID giving information about the picture
* generator. The known IDs are the following: */
@ -113,28 +113,28 @@ struct g3p_subheader {
*
* Then comes the specific subheader: */
struct c2p_subheader {
typedef struct g1m_classpad_picture_subheader_s {
/* "0100" */
uint8_t magic[4];
uint8_t g1m_classpad_picture_subheader_magic[4];
/* footer offset? `filesize - 0x254` */
uint32_t footer_offset;
uint32_t g1m_classpad_picture_subheader_footer_offset;
/* unknown */
uint16_t unknown2;
uint16_t g1m_classpad_picture_subheader__unknown0;
/* width (max for screen: 0x136 */
uint16_t width;
uint16_t g1m_classpad_picture_subheader_width;
/* height (max for screen: 0x191) */
uint16_t height;
uint16_t g1m_classpad_picture_subheader_height;
/* undocumented, again */
uint8_t undocumented2[18];
uint8_t g1m_classpad_picture_subheader__undocumented[18];
/* filesize - 0x258 */
uint32_t unknown_size3;
};
uint32_t g1m_classpad_picture_subheader__size3;
} g1m_classpad_picture_subheader_t;
/* Then there is the zlib header with default compression.
* The pixels format is R5G6B5.
@ -142,13 +142,13 @@ struct c2p_subheader {
* After the image, there is a footer, which is mainly undocumented, but
* here is what we've got: */
struct c2p_footer {
typedef struct g1m_classpad_picture_footer_s {
/* "0100", again */
uint8_t magic[4];
uint8_t g1m_classpad_picture_footer_magic[4];
/* and some undocumented stuff */
uint8_t undocumented[0xE4];
};
uint8_t g1m_classpad_picture_footer__undocumented[0xE4];
} g1m_classpad_picture_footer_s;
# pragma pack()
#endif /* LIBG1M_FORMAT_STD_PICTURE_H */

View File

@ -38,18 +38,18 @@
* part, then with a type-specific part (then unused bytes if the subheader
* is less than 28-bytes long). Here is its structure: */
struct storage_entry {
typedef struct g1m_storage_entry_s {
/* the type number - see below */
uint16_t type;
uint16_t g1m_storage_entry_type;
/* the number of the entry; if this field is 0x00, just ignore the entry.
* we don't know why entries with this field set to 0x00 exist...
* (probably backups?) */
uint16_t id;
uint16_t g1m_storage_entry_id;
/* the raw subheader */
uint8_t raw_subheader[28];
};
uint8_t g1m_storage_entry_raw_subheader[28];
} g1m_storage_entry_t;
/* The `type` is composed of three nibbles of identification (`type & 0xFFF`)
* and a (high) nibble of special properties, keep that in mind.
@ -94,15 +94,14 @@ struct storage_entry {
* Their special nibble is either 0x04 or 0x00, the signification of it is not
* known to me yet. Here is their subheader structure: */
struct storage_sector {
typedef struct g1m_storage_sector_s {
/* the sector start address - 0xFF */
uint32_t startaddr;
uint32_t g1m_storage_sector_startaddr;
/* the sector ID - probably not using the UUID so sectors can
* not be set as parent nodes :) */
uint32_t logical_sector_number;
};
uint32_t g1m_storage_sector_logical_sector_number;
} g1m_storage_sector_t;
/* ************************************************************************** */
/* Directories */
/* ************************************************************************** */
@ -111,15 +110,14 @@ struct storage_sector {
* Their special nibble is either 0x05 if active or 0x00 if deleted.
* Here is their subheader structure: */
struct storage_directory {
typedef struct g1m_storage_directory_s {
/* the parent type and id */
uint16_t parent_type;
uint16_t parent_id;
uint16_t g1m_storage_directory_parent_type;
uint16_t g1m_storage_directory_parent_id;
/* the name (FONTCHARACTER-encoded) */
FONTCHARACTER name[12];
};
FONTCHARACTER g1m_storage_directory_name[12];
} g1m_storage_directory_t;
/* ************************************************************************** */
/* Files */
/* ************************************************************************** */
@ -128,15 +126,14 @@ struct storage_directory {
* Their special nibble have the same meaning that for directories.
* Here is their subheader structure: */
struct storage_file {
typedef struct g1m_storage_file_s {
/* the parent type and id (not functional?) */
uint16_t parent_type;
uint16_t parent_id;
uint16_t g1m_storage_file_parent_type;
uint16_t g1m_storage_file_parent_id;
/* the name (FONTCHARACTER-encoded) */
FONTCHARACTER name[12];
};
FONTCHARACTER g1m_storage_file_name[12];
} g1m_storage_file_t;
/* ************************************************************************** */
/* File fragments */
/* ************************************************************************** */
@ -159,25 +156,25 @@ struct storage_file {
/* Why is the file type here and not in the file header? I don't know.
* And here is the fragments' subheader structure: */
struct storage_fragment {
typedef struct g1m_storage_fragment_s {
/* the parent (file node) type and id */
uint16_t parent_type;
uint16_t parent_id;
uint16_t g1m_storage_fragment_parent_type;
uint16_t g1m_storage_fragment_parent_id;
/* the file type */
uint16_t file_type;
uint16_t g1m_storage_fragment_file_type;
/* the fragment count and id */
uint16_t fragment_count;
uint16_t fragment_id;
uint16_t g1m_storage_fragment_count;
uint16_t g1m_storage_fragment_id;
/* the sector id that the fragment is linked to */
uint16_t fragment_sector_id;
uint16_t g1m_storage_fragment_sector_id;
/* number and offset in the sector of the fragment's bytes */
uint16_t data_offset;
uint16_t data_length;
};
uint16_t g1m_storage_fragment_data_offset;
uint16_t g1m_storage_fragment_data_length;
} g1m_storage_fragment_t;
# pragma pack()
#endif /* LIBG1M_FORMAT_STORAGE_H */

View File

@ -82,17 +82,14 @@ typedef struct g1m_version_s {
/* Handle structure */
/* ************************************************************************** */
typedef struct {
/* file type, the source destination platform */
g1m_type_t g1m_handle_type;
g1m_platform_t g1m_handle_platform;
/* file type, destination platform */
g1m_type_t g1m_handle_type;
g1m_platform_t g1m_handle_platform;
/* Add-in related data */
char g1m_handle_title[17];
char g1m_handle_intname[12];
g1m_version_t g1m_handle_version;
time_t g1m_handle_creation_date;
unsigned char *g1m_handle_content;
size_t g1m_handle_size;
time_t g1m_handle_creation_date;
unsigned char *g1m_handle_content;
size_t g1m_handle_size;
/* Lists for various purposes */
int g1m_handle_count;
@ -111,6 +108,14 @@ typedef struct {
/* E-activities related data */
g1m_line_t *g1m_handle_line;
/* some other data */
char g1m_handle_title[17];
char g1m_handle_intname[12];
g1m_version_t g1m_handle_version;
/* internal data */
g1m_mcsfile_t g1m_handle__setfile;
g1m_line_t g1m_handle__linedata;
} g1m_handle_t;

View File

@ -106,7 +106,7 @@
/* with expected types */
extern int g1m_decode_std(g1m_handle_t **handle, const char *path,
g1m_buffer_t *buffer,
struct standard_header*, g1m_type_t expected_types);
g1m_standard_header_t*, g1m_type_t expected_types);
/* w/o expected types */
int g1m_decode_casemul(g1m_handle_t **handle, g1m_buffer_t *buffer,
@ -119,20 +119,20 @@ int g1m_decode_grc(g1m_handle_t **handle, g1m_buffer_t *buffer);
/* ************************************************************************** */
# define G1M_STDFUNC(NAME) \
extern int g1m_decode_std_##NAME(g1m_handle_t **handle, g1m_buffer_t *buffer, \
struct standard_header *std);
g1m_standard_header_t *std);
# define G1M_PRIZMFUNC(NAME) \
extern int g1m_decode_std_cg_##NAME(g1m_handle_t **handle, \
g1m_buffer_t *buffer, \
struct standard_header *std, struct standard_subheader *sub, \
struct _prizm_subheader *pzm, uint32_t *check);
g1m_standard_header_t *std, g1m_standard_subheader_t *sub, \
g1m_standard_prizm_subheader_t *pzm, uint32_t *check);
# define G1M_CPFUNC(NAME) \
extern int g1m_decode_std_cp_##NAME(g1m_handle_t **handle, \
g1m_buffer_t *buffer, \
struct standard_header *std, struct standard_subheader *sub, \
struct _classpad_subheader *cp, uint32_t *check);
g1m_standard_header_t *std, g1m_standard_subheader_t *sub, \
g1m_standard_classpad_subheader_t *cp, uint32_t *check);
# define G1M_PICFUNC(NAME) \
extern int g1m_decode_std_##NAME(g1m_handle_t **handle, g1m_buffer_t *buffer, \
struct standard_header *std, struct standard_picheader *pic);
g1m_standard_header_t *std, g1m_standard_picheader_t *pic);
/* standard funcs */
G1M_STDFUNC(mcs)

View File

@ -167,30 +167,30 @@ typedef struct g1m_setup_s {
/* mcs file head */
typedef struct g1m_mcshead_s {
/* file main information */
g1m_mcstype_t g1m_mcshead_type;
g1m_mcsinfo_t g1m_mcshead_info;
unsigned int g1m_mcshead_flags;
unsigned int g1m_mcshead_id;
g1m_mcstype_t g1m_mcshead_type;
g1m_mcsinfo_t g1m_mcshead_info;
unsigned int g1m_mcshead_flags;
unsigned int g1m_mcshead_id;
/* content size */
int g1m_mcshead_count;
unsigned int g1m_mcshead_width;
unsigned int g1m_mcshead_height;
uint_fast32_t g1m_mcshead_size;
int g1m_mcshead_count;
unsigned int g1m_mcshead_width;
unsigned int g1m_mcshead_height;
uint_fast32_t g1m_mcshead_size;
/* raw data */
unsigned int g1m_mcshead_rawtype;
g1m_pictureformat_t g1m_mcshead_picformat;
/* strings */
char g1m_mcshead_name[13];
char g1m_mcshead_password[9];
char g1m_mcshead_name[13];
char g1m_mcshead_password[9];
/* raw string data */
unsigned char g1m_mcshead_group[17];
unsigned char g1m_mcshead_dirname[9];
unsigned char g1m_mcshead_appname[4];
unsigned char g1m_mcshead_datatype[3];
unsigned char g1m_mcshead_group[17];
unsigned char g1m_mcshead_dirname[9];
unsigned char g1m_mcshead_appname[4];
unsigned char g1m_mcshead_datatype[3];
} g1m_mcshead_t;
/* mcs file */
@ -200,10 +200,10 @@ typedef struct g1m_mcshead_s {
(F)->g1m_mcsfile_head.g1m_mcshead_password[0] = 0
typedef struct g1m_mcsfile_s {
/* head */
g1m_mcshead_t g1m_mcsfile_head;
g1m_mcshead_t g1m_mcsfile_head;
/* content (useful when not read) */
char *g1m_mcsfile_content;
char *g1m_mcsfile_content;
/* variables */
g1m_mcscell_t g1m_mcsfile_var;
@ -211,11 +211,11 @@ typedef struct g1m_mcsfile_s {
g1m_mcscell_t **g1m_mcsfile_cells;
/* for pictures and captures */
uint32_t **g1m_mcsfile_pic; /* 0x0RGB */
uint32_t ***g1m_mcsfile_pics;
uint32_t **g1m_mcsfile_pic; /* 0x0RGB */
uint32_t ***g1m_mcsfile_pics;
/* for settings */
g1m_setup_t g1m_mcsfile_setup;
g1m_setup_t g1m_mcsfile_setup;
} g1m_mcsfile_t;
#endif /* LIBG1M_MCS_H */

View File

@ -87,26 +87,27 @@ static void *lookup_cas_decode(g1m_mcstype_t type, int heads)
static int decode_cas50(g1m_mcshead_t *head, g1m_buffer_t *buffer, uint8_t csum)
{
/* read the raw header */
DREAD(hd, _cas50)
DREAD(hd, g1m_cas50_s)
log_info("Raw CAS50 (CASPRO) header content (app: '%.3s'):",
head->g1m_mcshead_appname);
logm_info(&hd, sizeof(struct _cas50));
logm_info(&hd, sizeof(g1m_cas50_t));
/* check the checksum */
csum += g1m_checksum8(&hd, sizeof(struct _cas50) - 1);
csum += g1m_checksum8(&hd, sizeof(g1m_cas50_t) - 1);
csum = ~csum + 1;
if (csum != hd.checksum) {
if (csum != hd.g1m_cas50_checksum) {
log_error("Checksum mismatch: expected 0x%02X, got 0x%02X",
hd.checksum, csum);
hd.g1m_cas50_checksum, csum);
return (g1m_error_checksum);
}
/* copy the basic information */
g1m_maketype_cas(head, (char*)hd.data);
head->g1m_mcshead_size = be16toh(hd.height) - 2 /* checksum, colon */;
char *end = memchr(hd.name, 0xFF, 8);
size_t len = end ? (size_t)(end - (char*)hd.name) : 8;
memcpy(head->g1m_mcshead_name, hd.name, len);
g1m_maketype_cas(head, (char*)hd.g1m_cas50_data);
head->g1m_mcshead_size = be16toh(hd.g1m_cas50_height)
- 2 /* checksum, colon */;
char *end = memchr(hd.g1m_cas50_name, 0xFF, 8);
size_t len = end ? (size_t)(end - (char*)hd.g1m_cas50_name) : 8;
memcpy(head->g1m_mcshead_name, hd.g1m_cas50_name, len);
head->g1m_mcshead_name[len] = 0;
/* read specific data */
@ -114,9 +115,9 @@ static int decode_cas50(g1m_mcshead_t *head, g1m_buffer_t *buffer, uint8_t csum)
case g1m_mcstype_program:;
/* copy password */
head->g1m_mcshead_flags |= g1m_mcsflag_unfinished;
end = memchr(hd.aux, 0xFF, 8);
len = end ? (size_t)(end - (char*)hd.aux) : 8;
memcpy(head->g1m_mcshead_password, hd.aux, len);
end = memchr(hd.g1m_cas50_aux, 0xFF, 8);
len = end ? (size_t)(end - (char*)hd.g1m_cas50_aux) : 8;
memcpy(head->g1m_mcshead_password, hd.g1m_cas50_aux, len);
head->g1m_mcshead_password[len] = 0;
log_info("Is a program of %" PRIuFAST32 " bytes",
head->g1m_mcshead_size);
@ -124,8 +125,8 @@ static int decode_cas50(g1m_mcshead_t *head, g1m_buffer_t *buffer, uint8_t csum)
case g1m_mcstype_variable:
case g1m_mcstype_matrix:
case g1m_mcstype_list:
head->g1m_mcshead_height = be16toh(hd.height) & 0xFF;
head->g1m_mcshead_width = be16toh(hd.width) & 0xFF;
head->g1m_mcshead_height = be16toh(hd.g1m_cas50_height) & 0xFF;
head->g1m_mcshead_width = be16toh(hd.g1m_cas50_width) & 0xFF;
head->g1m_mcshead_count = head->g1m_mcshead_height;
if (head->g1m_mcshead_width && head->g1m_mcshead_height)
head->g1m_mcshead_flags |= g1m_mcsflag_unfinished;
@ -154,8 +155,9 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer)
/* read beginning of the header, check if is an extended header */
uint8_t buf[39]; READ(buf, 4)
uint8_t csum = g1m_checksum8(buf, 4);
struct casdyn *dhd = (void*)buf;
if (!g1m_maketype_casapp(head, dhd->ext, (char*)dhd->app))
g1m_casdyn_t *dhd = (void*)buf;
if (!g1m_maketype_casapp(head, dhd->g1m_casdyn_ext,
(char*)dhd->g1m_casdyn_app))
switch (head->g1m_mcshead_info) {
case g1m_mcsinfo_cas50: return (decode_cas50(head, buffer, csum));
//case g1m_mcsinfo_cas100: return (decode_cas100(head, buffer));
@ -166,25 +168,25 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer)
}
/* is a CAS40 head, read it. */
READ(&buf[4], 35) struct cas40 *hd = (void*)buf;
READ(&buf[4], 35) g1m_cas40_t *hd = (void*)buf;
csum += g1m_checksum8(&buf[4], 34);
log_info("Raw CAS40 (CAS) header:");
logm_info(hd, sizeof(struct cas40));
if (g1m_maketype_cas(head, (char*)hd->data))
logm_info(hd, sizeof(g1m_cas40_t));
if (g1m_maketype_cas(head, (char*)hd->g1m_cas40_data))
return (g1m_error_unrecognized);
if (~csum + 1 != hd->checksum)
if (~csum + 1 != hd->g1m_cas40_checksum)
return (g1m_error_checksum);
/* fill the handle */
memset(head, 0, sizeof(g1m_mcshead_t));
head->g1m_mcshead_info = g1m_mcsinfo_cas40;
memcpy(head->g1m_mcshead_name, hd->filename, 12);
memcpy(head->g1m_mcshead_name, hd->g1m_cas40_filename, 12);
head->g1m_mcshead_name[12] = 0;
/* type specific things */
if (head->g1m_mcshead_type == g1m_mcstype_program) {
struct cas_spe_program *spe = (void*)hd->misc;
head->g1m_mcshead_size = be16toh(spe->length);
g1m_cas_spe_program_t *spe = (void*)hd->g1m_cas40_misc;
head->g1m_mcshead_size = be16toh(spe->g1m_cas_spe_program_length);
/* TODO: store flags? */
}

View File

@ -44,12 +44,13 @@
static int read_internal(g1m_buffer_t *buffer, uint32_t signature,
uint_fast32_t version)
{
DREAD(hd, casemul_internal_header)
DREAD(hd, g1m_casemul_intheader_s)
/* check type */
if (signature != hd.signature) {
if (signature != hd.g1m_casemul_intheader_signature) {
#if LOGLEVEL <= ll_error
const char *a = (char*)&signature, *b = (char*)&hd.signature;
const char *a = (char*)&signature, *b =
(char*)&hd.g1m_casemul_intheader_signature;
log_error("signature mismatch!");
log_error("expected '%c%c%c%c', got '%c%c%c%c'",
a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
@ -58,10 +59,10 @@ static int read_internal(g1m_buffer_t *buffer, uint32_t signature,
}
/* check version */
if (le32toh(hd.version) != version) {
if (hd.g1m_casemul_intheader_version != version) {
log_error("version mismatch!");
log_error("epxected %08" PRIxFAST32 ", got %08" PRIx32,
version, hd.version);
version, hd.g1m_casemul_intheader_version);
return (g1m_error_magic);
}
@ -103,7 +104,6 @@ static int read_top(g1m_buffer_t *buffer, char *name, uint_fast32_t *length,
/* no error! */
return (0);
}
/* ************************************************************************** */
/* Intermediate functions */
/* ************************************************************************** */
@ -136,19 +136,21 @@ static int read_picture(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer,
return (err);
/* specific things */
DREAD(pct, casemul_pict_header)
log_info("picture dimension is %d*%dpx", pct.width, pct.height);
DREAD(pct, g1m_casemul_pict_header_s)
log_info("picture dimension is %d*%dpx", pct.g1m_casemul_pict_header_width,
pct.g1m_casemul_pict_header_height);
/* read all of the pixels */
unsigned int total = pct.width * pct.height;
unsigned int total = pct.g1m_casemul_pict_header_width *
pct.g1m_casemul_pict_header_height;
uint8_t rawpx[total]; READ(rawpx, total)
uint8_t *px = rawpx;
/* make the head and allocate file */
g1m_mcshead_t head = {
.g1m_mcshead_type = g1m_mcstype_capture,
.g1m_mcshead_width = pct.width,
.g1m_mcshead_height = pct.height,
.g1m_mcshead_width = pct.g1m_casemul_pict_header_width,
.g1m_mcshead_height = pct.g1m_casemul_pict_header_height,
};
memcpy(head.g1m_mcshead_name, name, strlen(name) + 1);
head.g1m_mcshead_id = name[7] - '0';
@ -157,7 +159,8 @@ static int read_picture(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer,
/* set the pixels */
uint32_t **img = (*pfile)->g1m_mcsfile_pics[0];
for (int x = 0; x < pct.width; x++) for (int y = 0; y < pct.height; y++)
for (int x = 0; x < pct.g1m_casemul_pict_header_width; x++)
for (int y = 0; y < pct.g1m_casemul_pict_header_height; y++)
img[y][x] = colours[*px++];
/* finish */
@ -185,9 +188,9 @@ static int read_matrix(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer,
return (err);
/* read specific things */
DREAD(mtx, casemul_mtrx_header)
unsigned int width = e32toh(mtx.lines) & 0x7FFF,
height = e32toh(mtx.columns) & 0x7FFF;
DREAD(mtx, g1m_casemul_mtrx_header_s)
unsigned int width = e32toh(mtx.g1m_casemul_mtrx_header_lines) & 0x7FFF,
height = e32toh(mtx.g1m_casemul_mtrx_header_columns) & 0x7FFF;
/* read double tab */
unsigned int total = width * height;
@ -252,8 +255,8 @@ static int read_list(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer,
return (err);
/* read specific things */
DREAD(lst, casemul_list_header)
int len = le32toh(lst.lines) & 0x7FFF;
DREAD(lst, g1m_casemul_list_header_s)
int len = le32toh(lst.g1m_casemul_list_header_lines) & 0x7FFF;
log_info("%d elements in list", len);
/* read double tab */
@ -312,21 +315,18 @@ int g1m_decode_casemul(g1m_handle_t **h, g1m_buffer_t *buffer, int big_endian)
{
int err;
/* read the overall header's internal header end */
struct casemul_internal_header overall_int = {
.signature = MAKELONG('CA', 'FS')};
READ(&overall_int.version, 8);
if (e32toh(overall_int.version) != 0x100)
return (g1m_error_magic);
/* read the overall (global) header */
DREAD(glb, casemul_header)
DREAD(glb, g1m_casemul_header_s)
#if LOGLEVEL <= ll_info
glb.source_offset = e32toh(glb.source_offset);
glb.compiled_offset = e32toh(glb.compiled_offset);
log_info("Header source offset is: 0x%08X", glb.source_offset);
if (glb.flags & casemul_compiled)
log_info("Header compiled offset is: 0x%08X", glb.compiled_offset);
glb.g1m_casemul_header_source_offset =
e32toh(glb.g1m_casemul_header_source_offset);
glb.g1m_casemul_header_compiled_offset =
e32toh(glb.g1m_casemul_header_compiled_offset);
log_info("Header source offset is: 0x%08X",
glb.g1m_casemul_header_source_offset);
if (glb.g1m_casemul_header_flags & casemul_compiled)
log_info("Header compiled offset is: 0x%08X",
glb.g1m_casemul_header_compiled_offset);
else
log_info("The file has got no compiled part.");
#endif
@ -334,17 +334,19 @@ int g1m_decode_casemul(g1m_handle_t **h, g1m_buffer_t *buffer, int big_endian)
/* read the source header */
if ((err = read_internal(buffer, MAKELONG('SR', 'CE'), VER)))
return (err);
DREAD(src, casemul_source_header)
DREAD(src, g1m_casemul_source_header_s)
/* make the handle */
err = g1m_make_mcs(h, /* src.programs + */ src.pictures + src.matrixes
+ src.lists);
err = g1m_make_mcs(h, /* src.programs */ 0
+ src.g1m_casemul_source_header_pictures
+ src.g1m_casemul_source_header_matrixes
+ src.g1m_casemul_source_header_lists);
if (err) return (err);
g1m_handle_t *handle = *h;
/* read each program; TODO: put this in a function when token parsing
* is managed. */
for (int i = 0; i < src.programs; i++) {
for (int i = 0; i < src.g1m_casemul_source_header_programs; i++) {
log_info("Reading program #%d", i + 1);
log_warn("Program content will be skipped!");
/* general record things */
@ -354,15 +356,16 @@ int g1m_decode_casemul(g1m_handle_t **h, g1m_buffer_t *buffer, int big_endian)
goto fail;
/* specific things */
GDREAD(prg, casemul_prog_header)
prg.length = le32toh(prg.length);
GDREAD(prg, g1m_casemul_prog_header_s)
prg.g1m_casemul_prog_header_length =
e32toh(prg.g1m_casemul_prog_header_length);
/* TODO: decode using tokens (cf. refc and libfc) */
SKIP(prg.length)
SKIP(prg.g1m_casemul_prog_header_length)
}
/* read each picture */
for (int i = 0; i < src.pictures; i++) {
for (int i = 0; i < src.g1m_casemul_source_header_pictures; i++) {
log_info("Reading picture #%d", i + 1);
err = read_picture(&handle->g1m_handle_files[handle->g1m_handle_count],
buffer, big_endian);
@ -371,7 +374,7 @@ int g1m_decode_casemul(g1m_handle_t **h, g1m_buffer_t *buffer, int big_endian)
}
/* read each matrix */
for (int i = 0; i < src.matrixes; i++) {
for (int i = 0; i < src.g1m_casemul_source_header_matrixes; i++) {
log_info("Reading matrix #%d", i + 1);
err = read_matrix(&handle->g1m_handle_files[handle->g1m_handle_count],
buffer, big_endian);
@ -380,7 +383,7 @@ int g1m_decode_casemul(g1m_handle_t **h, g1m_buffer_t *buffer, int big_endian)
}
/* read each list */
for (int i = 0; i < src.lists; i++) {
for (int i = 0; i < src.g1m_casemul_source_header_lists; i++) {
log_info("Reading list #%d", i + 1);
err = read_list(&handle->g1m_handle_files[handle->g1m_handle_count],
buffer, big_endian);

View File

@ -115,17 +115,24 @@ int g1m_decode(g1m_handle_t **handle, const char *path, g1m_buffer_t *buffer,
}
/* identify a Casemul file */
READ(&buf[3], 1)
READ(&buf[3], 9)
int casemul_be = !memcmp(buf, "CAFS", 4);
if (casemul_be || !memcmp(buf, "ACFS", 4)) {
g1m_casemul_intheader_t *ch = (void*)buf;
uint32_t ver = casemul_be ? be32toh(ch->g1m_casemul_intheader_version)
: le32toh(ch->g1m_casemul_intheader_version);
uint32_t siz = casemul_be ? le32toh(ch->g1m_casemul_intheader_size)
: le32toh(ch->g1m_casemul_intheader_size);
if (ver != 0x100 || siz != sizeof(g1m_casemul_header_t))
return (g1m_error_magic);
if (expected_types && !(expected_types & g1m_type_mcs))
return (g1m_error_wrong_type);
return (g1m_decode_casemul(handle, buffer, casemul_be));
}
/* identify a standard header (send a _copy_) */
READ(&buf[4], 0x1C)
READ(&buf[12], 0x14)
uint8_t altbuf[0x20]; memcpy(altbuf, buf, 0x20);
return (g1m_decode_std(handle, path, buffer,
(struct standard_header*)altbuf, expected_types));
(g1m_standard_header_t*)altbuf, expected_types));
}

View File

@ -35,12 +35,12 @@ int g1m_decode_mcs_cells(g1m_mcsfile_t **handle, g1m_buffer_t *buffer,
uint_fast32_t y, x;
/* read header */
DREAD(hd, mcs_cellsheader)
DREAD(hd, g1m_mcs_cellsheader_s)
/* log info */
uint_fast32_t w = be16toh(hd.width),
uint_fast32_t w = be16toh(hd.g1m_mcs_cellsheader_width),
h = (head->g1m_mcshead_type & g1m_mcstype_list)
? 1 : be16toh(hd.height);
? 1 : be16toh(hd.g1m_mcs_cellsheader_height);
log_info("Matrix size is %" PRIuFAST32 "*%" PRIuFAST32, w, h);
/* make final head */

View File

@ -32,13 +32,11 @@ int g1m_decode_mcs_capture(g1m_mcsfile_t **handle, g1m_buffer_t *buffer,
g1m_mcshead_t *head)
{
/* read header */
DREAD(hd, mcs_captureheader)
hd.width = be16toh(hd.width);
hd.height = be16toh(hd.height);
DREAD(hd, g1m_mcs_captureheader_s)
/* make final head and file */
head->g1m_mcshead_width = hd.width;
head->g1m_mcshead_height = hd.height;
head->g1m_mcshead_width = be16toh(hd.g1m_mcs_captureheader_width);
head->g1m_mcshead_height = be16toh(hd.g1m_mcs_captureheader_height);
int err = g1m_make_mcsfile(handle, head);
if (err) return (err);
g1m_mcsfile_t *h = *handle;

View File

@ -34,13 +34,14 @@ int g1m_decode_mcs_program(g1m_mcsfile_t **handle, g1m_buffer_t *buffer,
int err;
/* read header */
DREAD(hd, mcs_programheader)
log_info("Program password is '%.8s'.", hd.password);
DREAD(hd, g1m_mcs_programheader_s)
log_info("Program password is '%.8s'.", hd.g1m_mcs_programheader_password);
/* make final head and file */
strncpy(head->g1m_mcshead_password, (char*)hd.password, 8);
strncpy(head->g1m_mcshead_password,
(char*)hd.g1m_mcs_programheader_password, 8);
head->g1m_mcshead_password[8] = 0;
head->g1m_mcshead_size -= sizeof(struct mcs_programheader);
head->g1m_mcshead_size -= sizeof(g1m_mcs_programheader_t);
head->g1m_mcshead_size += 1; /* terminating zero - XXX: keep it? */
err = g1m_make_mcsfile(handle, head);
if (err) return (err);

View File

@ -32,15 +32,16 @@ int g1m_decode_mcs_spreadsheet(g1m_mcsfile_t **handle, g1m_buffer_t *buffer,
g1m_mcshead_t *head)
{
/* read header */
DREAD(hd, mcs_spreadsheetheader)
if (hd.has_subheader != 0x01)
DREAD(hd, g1m_mcs_spreadsheet_header_s)
if (hd.g1m_mcs_spreadsheet_header_has_subheader != 0x01)
return (0);
/* read subheader */
DREAD(shd, mcs_spreadsheet_subheader)
uint_fast32_t colcount = hd.column_count;
DREAD(shd, g1m_mcs_spreadsheet_subheader_s)
uint_fast32_t colcount = hd.g1m_mcs_spreadsheet_header_column_count;
colcount = be32toh(colcount << 8);
shd.defs_size = be32toh(shd.defs_size);
shd.g1m_mcs_spreadsheet_subheader_defs_size =
be32toh(shd.g1m_mcs_spreadsheet_subheader_defs_size);
/* prepare */
g1m_mcscell_t cells[1000 * colcount];

View File

@ -88,7 +88,6 @@ static int find_decode_function(g1m_platform_t platform, g1m_type_t type,
*rd = c->decode;
return (0);
}
/* ************************************************************************** */
/* Main standard header decoding function */
/* ************************************************************************** */
@ -105,38 +104,43 @@ static int find_decode_function(g1m_platform_t platform, g1m_type_t type,
*/
int g1m_decode_std(g1m_handle_t **handle, const char *path,
g1m_buffer_t *buffer,
struct standard_header *std, g1m_type_t expected_types)
g1m_buffer_t *buffer, g1m_standard_header_t *std,
g1m_type_t expected_types)
{
int err;
/* reverse the standard header */
uint8_t *u = (uint8_t*)std;
uint32_t check = g1m_checksum32(std, sizeof(struct standard_header), 0);
for (size_t i = 0; i < sizeof(struct standard_header); i++)
uint32_t check = g1m_checksum32(std, sizeof(g1m_standard_header_t), 0);
for (size_t i = 0; i < sizeof(g1m_standard_header_t); i++)
u[i] = ~u[i];
/* print header */
log_info("Raw inverted standard header is:");
logm_info(std, sizeof(struct standard_header));
std->filesize = be32toh(std->filesize);
std->number = be16toh(std->number);
logm_info(std, sizeof(g1m_standard_header_t));
std->g1m_standard_header_filesize =
be32toh(std->g1m_standard_header_filesize);
std->g1m_standard_header_number =
be16toh(std->g1m_standard_header_number);
/* get the type */
g1m_platform_t platform; g1m_type_t type;
const char *type_string; unsigned int mflags;
decode_func rd;
if (g1m_maketype_std(path, std->main_id, std->subtype, &type_string,
&mflags, &platform, &type))
if (g1m_maketype_std(path, std->g1m_standard_header_main_id,
std->g1m_standard_header_subtype, &type_string, &mflags, &platform,
&type))
return (g1m_error_magic);
log_info("Standard Header type is '%s'.", type_string);
/* check control bytes */
if (mflags & g1m_stdflag_check1
&& std->control != ((std->filesize + 0x41) & 0xff)) {
&& std->g1m_standard_header_control
!= ((std->g1m_standard_header_filesize + 0x41) & 0xff)) {
log_info("First control byte isn't right.");
return (g1m_error_magic);
} else if (mflags & g1m_stdflag_check2
&& std->control2 != ((std->filesize + 0xb8) & 0xff)) {
&& std->g1m_standard_header_control2
!= ((std->g1m_standard_header_filesize + 0xb8) & 0xff)) {
log_info("Second control byte isn't right.");
return (g1m_error_magic);
}
@ -144,9 +148,9 @@ int g1m_decode_std(g1m_handle_t **handle, const char *path,
/* check if there is a standard subheader */
if (mflags & g1m_stdflag_sub) {
log_info("Has a Standard Subheader!");
DREAD(hd, standard_subheader)
if (g1m_maketype_sub(hd.filetype, hd.platform,
&mflags, &type, &platform))
DREAD(hd, g1m_standard_subheader_s)
if (g1m_maketype_sub(hd.g1m_standard_subheader_filetype,
hd.g1m_standard_subheader_platform, &mflags, &type, &platform))
return (g1m_error_magic);
/* TODO: controls */
@ -157,19 +161,19 @@ int g1m_decode_std(g1m_handle_t **handle, const char *path,
return (g1m_error_wrong_type);
/* read and decode for specific platforms */
check = g1m_checksum32(&hd.filetype,
sizeof(struct standard_subheader) - 4, check);
check = g1m_checksum32(&hd.g1m_standard_subheader_filetype,
sizeof(g1m_standard_header_t) - 4, check);
if (platform == g1m_platform_cp) {
DREAD(shd, _classpad_subheader)
check = g1m_checksum32(&shd, sizeof(struct _classpad_subheader),
check);
DREAD(shd, g1m_standard_classpad_subheader_s)
check = g1m_checksum32(&shd,
sizeof(g1m_standard_classpad_subheader_t), check);
/* decode the file content */
err = (*rd)(handle, buffer, std, &hd, &shd, &check);
if (err) return (err);
} else if (platform == g1m_platform_cg) {
DREAD(shd, _prizm_subheader)
check = g1m_checksum32(&shd, sizeof(struct _prizm_subheader),
DREAD(shd, g1m_standard_prizm_subheader_s)
check = g1m_checksum32(&shd, sizeof(g1m_standard_prizm_subheader_t),
check);
/* decode the file content */
@ -179,13 +183,14 @@ int g1m_decode_std(g1m_handle_t **handle, const char *path,
/* read the footer */
uint32_t endcheck; GREAD(&endcheck, sizeof(uint32_t))
err = g1m_error_checksum;
if (be32toh(endcheck) != be32toh(hd.checksum))
if (be32toh(endcheck)
!= be32toh(hd.g1m_standard_subheader_checksum))
goto fail;
}
/* check the sum */
err = g1m_error_checksum;
if (check != be32toh(hd.checksum))
if (check != be32toh(hd.g1m_standard_subheader_checksum))
goto fail;
/* no error */
@ -195,16 +200,17 @@ int g1m_decode_std(g1m_handle_t **handle, const char *path,
/* check if there is a standard picture header */
if (mflags & g1m_stdflag_pic) {
log_info("Has a Standard Picture Header!");
DREAD(hd, standard_picheader)
DREAD(hd, g1m_standard_picheader_s)
/* correct the type; TODO: hardcode less */
type = g1m_type_picture;
if (!memcmp(hd.cp, "CC", 2))
if (!memcmp(hd.g1m_standard_picheader_cp, "CC", 2))
platform = g1m_platform_cp;
else if (!memcmp(hd.cp, "CP", 2))
else if (!memcmp(hd.g1m_standard_picheader_cp, "CP", 2))
platform = g1m_platform_cg;
else {
log_error("Unknown magic sequence: '%.2s'", hd.cp);
log_error("Unknown magic sequence: '%.2s'",
hd.g1m_standard_picheader_cp);
return (g1m_error_magic);
}
@ -214,13 +220,15 @@ int g1m_decode_std(g1m_handle_t **handle, const char *path,
/* check the obfuscation bytes; imitates syscall 0x0C12
* http://bible.planet-casio.com/simlo/chm/v20/fxCG20_Bfile.htm */
if (std->obfuscated0 == std->subtype[0]
+ ((std->filesize & 0xFF00) >> 8) + (std->filesize & 0xFF)) {
std->obfuscated0 = 0;
std->obfuscated1 = 0;
if (std->g1m_standard_header_obfuscated0 ==
std->g1m_standard_header_subtype[0]
+ ((std->g1m_standard_header_filesize & 0xFF00) >> 8)
+ (std->g1m_standard_header_filesize & 0xFF)) {
std->g1m_standard_header_obfuscated0 = 0;
std->g1m_standard_header_obfuscated1 = 0;
} else {
std->obfuscated0 = 1;
std->obfuscated1 = 1;
std->g1m_standard_header_obfuscated0 = 1;
std->g1m_standard_header_obfuscated1 = 1;
}
/* call it */
@ -238,8 +246,10 @@ int g1m_decode_std(g1m_handle_t **handle, const char *path,
return (g1m_error_wrong_type);
/* log some data */
log_info("Standard Header filesize is %" PRIu32 "o.", std->filesize);
log_info("Standard Header num is %" PRIu16 ".", std->number);
log_info("Standard Header filesize is %" PRIu32 "o.",
std->g1m_standard_header_filesize);
log_info("Standard Header num is %" PRIu16 ".",
std->g1m_standard_header_number);
/* subdecode. */
return ((*rd)(handle, buffer, std));

View File

@ -31,30 +31,33 @@
*/
int g1m_decode_std_addin(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std)
g1m_standard_header_t *std)
{
int err = 0;
(void)std;
/* get the subheader */
DREAD(hd, g1a_subheader)
hd.filesize = be32toh(hd.filesize);
DREAD(hd, g1m_addin_subheader_s)
/* make the handle */
g1m_version_t version; g1m_decode_version((char*)hd.version, &version);
time_t created; g1m_decode_date((char*)hd.creation_date, &created);
size_t content_size = hd.filesize; /* already corrected */
content_size -= sizeof(struct standard_header)
+ sizeof(struct g1a_subheader);
g1m_version_t version; g1m_decode_version(
(char*)hd.g1m_addin_subheader_version, &version);
time_t created; g1m_decode_date(
(char*)hd.g1m_addin_subheader_creation_date, &created);
size_t content_size =
be32toh(hd.g1m_addin_subheader_filesize); /* already corrected */
content_size -= sizeof(g1m_standard_header_t)
+ sizeof(g1m_addin_subheader_t);
err = g1m_make_addin(h, g1m_platform_fx, content_size,
(char*)hd.title, (char*)hd.internal_name, &version, &created);
(char*)hd.g1m_addin_subheader_title,
(char*)hd.g1m_addin_subheader_internal_name, &version, &created);
if (err) return (err);
g1m_handle_t *handle = *h;
/* log info about the subheader */
log_info("title is '%s'", handle->g1m_handle_title);
log_info("internal name is '%s'", handle->g1m_handle_intname);
log_info("estrips count is %" PRIu8, hd.estrips_count);
log_info("estrips count is %" PRIu8, hd.g1m_addin_subheader_estrips_count);
log_info("version is %02u.%02u",
handle->g1m_handle_version.g1m_version_major,
handle->g1m_handle_version.g1m_version_minor);
@ -63,10 +66,10 @@ int g1m_decode_std_addin(g1m_handle_t **h, g1m_buffer_t *buffer,
/* fill icon */
g1m_decode_picture(handle->g1m_handle_icon_unsel,
g1m_pictureformat_1bit, hd.icon,
g1m_pictureformat_1bit, hd.g1m_addin_subheader_icon,
handle->g1m_handle_width, handle->g1m_handle_height);
g1m_decode_picture(handle->g1m_handle_icon_sel,
g1m_pictureformat_1bit_r, hd.icon,
g1m_pictureformat_1bit_r, hd.g1m_addin_subheader_icon,
handle->g1m_handle_width, handle->g1m_handle_height);
/* read content */
@ -96,31 +99,37 @@ fail:
*/
int g1m_decode_std_cp_addin(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std, struct standard_subheader *sub,
struct _classpad_subheader *cp, uint32_t *check)
g1m_standard_header_t *std, g1m_standard_subheader_t *sub,
g1m_standard_classpad_subheader_t *cp, uint32_t *check)
{
int err = 0;
(void)std; (void)cp;
/* read the add-in subheader */
DREAD(cphd, c1a_subheader)
*check = g1m_checksum32(&cphd, sizeof(struct c1a_subheader), *check);
DREAD(cphd, g1m_classpad_addin_subheader_s)
*check = g1m_checksum32(&cphd, sizeof(g1m_classpad_addin_subheader_t),
*check);
/* make the handle */
g1m_version_t version; g1m_decode_version((char*)sub->version, &version);
time_t created; g1m_decode_date((char*)sub->timestamp, &created);
size_t content_size = be32toh(sub->filesize) - 0x1000;
g1m_version_t version; g1m_decode_version(
(char*)sub->g1m_standard_subheader_version, &version);
time_t created; g1m_decode_date(
(char*)sub->g1m_standard_subheader_timestamp, &created);
size_t content_size = be32toh(sub->g1m_standard_subheader_filesize)
- 0x1000;
err = g1m_make_addin(h, g1m_platform_cp, content_size,
(char*)sub->title, (char*)sub->internal_name, &version, &created);
(char*)sub->g1m_standard_subheader_title,
(char*)sub->g1m_standard_subheader_internal_name,
&version, &created);
if (err) return (err);
g1m_handle_t *handle = *h;
/* decode pictures */
g1m_decode_picture(handle->g1m_handle_icon_unsel,
g1m_pictureformat_1bit_packed, cphd.icon,
g1m_pictureformat_1bit_packed, cphd.g1m_classpad_addin_subheader_icon,
handle->g1m_handle_width, handle->g1m_handle_height);
g1m_decode_picture(handle->g1m_handle_icon_sel,
g1m_pictureformat_1bit_packed_r, cphd.icon,
g1m_pictureformat_1bit_packed_r, cphd.g1m_classpad_addin_subheader_icon,
handle->g1m_handle_width, handle->g1m_handle_height);
/* log */
@ -160,36 +169,42 @@ fail:
*/
int g1m_decode_std_cg_addin(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std, struct standard_subheader *sub,
struct _prizm_subheader *prizm, uint32_t *check)
g1m_standard_header_t *std, g1m_standard_subheader_t *sub,
g1m_standard_prizm_subheader_t *prizm, uint32_t *check)
{
int err = 0;
(void)std; (void)prizm;
/* read the add-in subheader */
DREAD(cghd, g3a_subheader)
*check = g1m_checksum32(&cghd, sizeof(struct g3a_subheader), *check);
DREAD(cghd, g1m_prizm_addin_subheader_s)
*check = g1m_checksum32(&cghd, sizeof(g1m_prizm_addin_subheader_t), *check);
/* make the handle */
g1m_version_t version; g1m_decode_version((char*)sub->version, &version);
time_t created; g1m_decode_date((char*)sub->timestamp, &created);
size_t content_size = be32toh(sub->filesize);
content_size -= sizeof(struct standard_header)
+ sizeof(struct standard_subheader)
+ sizeof(struct _prizm_subheader) + sizeof(struct g3a_subheader)
g1m_version_t version; g1m_decode_version(
(char*)sub->g1m_standard_subheader_version, &version);
time_t created; g1m_decode_date(
(char*)sub->g1m_standard_subheader_timestamp, &created);
size_t content_size = be32toh(sub->g1m_standard_subheader_filesize);
content_size -= sizeof(g1m_standard_header_t)
+ sizeof(g1m_standard_subheader_t)
+ sizeof(g1m_standard_prizm_subheader_t)
+ sizeof(g1m_prizm_addin_subheader_t)
+ sizeof(uint32_t);
log_info("Content size is %" PRIuSIZE, content_size);
err = g1m_make_addin(h, g1m_platform_cg, content_size,
(char*)sub->internal_name, (char*)sub->title, &version, &created);
(char*)sub->g1m_standard_subheader_internal_name,
(char*)sub->g1m_standard_subheader_title, &version, &created);
if (err) return (err);
g1m_handle_t *handle = *h;
/* decode pictures */
g1m_decode_picture(handle->g1m_handle_icon_unsel,
g1m_pictureformat_16bit, cghd.unselected_icon_image,
g1m_pictureformat_16bit,
cghd.g1m_prizm_addin_subheader_unselected_icon_image,
handle->g1m_handle_width, handle->g1m_handle_height);
g1m_decode_picture(handle->g1m_handle_icon_sel,
g1m_pictureformat_16bit, cghd.selected_icon_image,
g1m_pictureformat_16bit,
cghd.g1m_prizm_addin_subheader_selected_icon_image,
handle->g1m_handle_width, handle->g1m_handle_height);
/* log */

View File

@ -51,34 +51,35 @@ static int eact_decode_content_eact(g1m_line_t *handle, uint8_t *buf,
if (!bufsize) return (0);
/* get e-act subheader */
if (bufsize < sizeof(struct eact_eactheader)) return (g1m_error_eof);
struct eact_eactheader ehd;
memcpy(&ehd, buf, sizeof(struct eact_eactheader));
/* correct endianess */
ehd.line_count = be32toh(ehd.line_count);
if (bufsize < sizeof(g1m_eact_content_eact_header_t))
return (g1m_error_eof);
g1m_eact_content_eact_header_t ehd;
memcpy(&ehd, buf, sizeof(g1m_eact_content_eact_header_t));
/* get the line descriptors
* there is actually a "bonus" line descriptor at the end, but the
* fact that we're using offsets lets us unaware of it. */
if (bufsize < sizeof(struct eact_eactheader)
+ (ehd.line_count + 1) * sizeof(struct line_descriptor))
uint32_t count = be32toh(ehd.g1m_eact_content_eact_header_line_count);
if (bufsize < sizeof(g1m_eact_content_eact_header_t)
+ (count + 1) * sizeof(g1m_eact_line_descriptor_t))
return (g1m_error_eof);
struct line_descriptor *lds = (void*)&buf[sizeof(struct eact_eactheader)];
g1m_eact_line_descriptor_t *lds =
(void*)&buf[sizeof(g1m_eact_content_eact_header_t)];
/* prepare the handle */
handle->g1m_line_count = 0;
handle->g1m_line__size = ehd.line_count;
handle->g1m_line__size = count;
handle->g1m_line_lines =
malloc(sizeof(g1m_line_t*) * handle->g1m_line__size);
if (!handle->g1m_line_lines) return (g1m_error_alloc);
bzero(handle->g1m_line_lines, sizeof(g1m_line_t*) * handle->g1m_line__size);
/* browse the lines */
log_info("%" PRIu32 " lines to browse", ehd.line_count);
if (ehd.line_count)
lds[0].entry_offset = be32toh(lds[0].entry_offset << 8);
for (i = 0; i < ehd.line_count; i++) {
log_info("%" PRIu32 " lines to browse", count);
if (count)
lds[0].g1m_eact_line_descriptor_offset =
be32toh(lds[0].g1m_eact_line_descriptor_offset << 8);
for (i = 0; i < count; i++) {
/* allocate line */
g1m_line_t *line = malloc(sizeof(g1m_line_t));
err = g1m_error_alloc;
@ -89,18 +90,21 @@ static int eact_decode_content_eact(g1m_line_t *handle, uint8_t *buf,
* if there is no next line (last line), then the data left will be
* attributed to the line. */
size_t linesize;
if (i == ehd.line_count - 1)
linesize = bufsize - lds[i].entry_offset;
if (i == count - 1)
linesize = bufsize - lds[i].g1m_eact_line_descriptor_offset;
else {
/* correct endianess of the next element */
lds[i + 1].entry_offset = be32toh(lds[i + 1].entry_offset << 8);
lds[i + 1].g1m_eact_line_descriptor_offset =
be32toh(lds[i + 1].g1m_eact_line_descriptor_offset << 8);
/* then calculate */
linesize = lds[i + 1].entry_offset - lds[i].entry_offset;
linesize = lds[i + 1].g1m_eact_line_descriptor_offset
- lds[i].g1m_eact_line_descriptor_offset;
}
/* store current info */
uint_fast8_t entry_type = lds[i].entry_type;
uint_fast32_t entry_offset = lds[i].entry_offset;
uint_fast8_t entry_type = lds[i].g1m_eact_line_descriptor_type;
uint_fast32_t entry_offset =
lds[i].g1m_eact_line_descriptor_offset;
/* check if buffer is big enough */
err = g1m_error_eof;
@ -161,18 +165,19 @@ static int eact_decode_line_content(g1m_line_t *handle, uint8_t *buf,
size_t size)
{
/* read content header */
size_t could_read = min(size, sizeof(struct eact_contentheader));
size_t could_read = min(size, sizeof(g1m_eact_content_header_t));
if (could_read < 9) return (g1m_error_eof);
struct eact_contentheader hd = {};
g1m_eact_content_header_t hd = {};
memcpy(&hd, buf, could_read);
/* store info */
bzero(handle->g1m_line_name, 17);
size_t namesize = max(could_read - 8, 16);
strncpy(handle->g1m_line_name, (char*)hd.name, namesize);
strncpy(handle->g1m_line_name, (char*)hd.g1m_eact_content_header_name,
namesize);
/* log info */
log_info("Type is '%.8s'", hd.type);
log_info("Type is '%.8s'", hd.g1m_eact_content_header_type);
log_info("Name is '%s'", handle->g1m_line_name);
/* prepare for next */
@ -182,7 +187,7 @@ static int eact_decode_line_content(g1m_line_t *handle, uint8_t *buf,
/* check for content type */
struct eact_content_type_corresp *ctype = eact_content_types;
while (ctype->decode) {
if (!memcmp(hd.type, ctype->type, 8))
if (!memcmp(hd.g1m_eact_content_header_type, ctype->type, 8))
break ;
ctype++;
}
@ -375,19 +380,19 @@ struct eact_line_type_corresp {
/* All correspondances */
static struct eact_line_type_corresp eact_line_types[] = {
{eact_ltype_calc, eact_decode_line_calculation,
{g1m_eact_ltype_calc, eact_decode_line_calculation,
"calculation"},
{eact_ltype_calc_result, eact_decode_line_result,
{g1m_eact_ltype_calc_result, eact_decode_line_result,
"calculation result"},
{eact_ltype_content, eact_decode_line_content,
{g1m_eact_ltype_content, eact_decode_line_content,
"content"},
{eact_ltype_stdheading, eact_decode_line_stdheading,
{g1m_eact_ltype_stdheading, eact_decode_line_stdheading,
"standard heading"},
{eact_ltype_picture, eact_decode_line_picture,
{g1m_eact_ltype_picture, eact_decode_line_picture,
"picture"},
{eact_ltype_text, eact_decode_line_text,
{g1m_eact_ltype_text, eact_decode_line_text,
"pure text"},
{eact_ltype_code, eact_decode_line_code,
{g1m_eact_ltype_code, eact_decode_line_code,
"text mixed with functions"},
{}
};
@ -425,7 +430,6 @@ static int eact_decode_line(g1m_line_t *handle, uint8_t *buf, size_t size,
log_info("line type is '%s' (0x%02x)", linetype->info, type);
return ((*linetype->decode)(handle, buf, size));
}
/* ************************************************************************** */
/* Main parsing functions */
/* ************************************************************************** */
@ -441,22 +445,22 @@ static int eact_decode_line(g1m_line_t *handle, uint8_t *buf, size_t size,
*/
int g1m_decode_std_eact(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std)
g1m_standard_header_t *std)
{
(void)std; int err;
/* decode the header */
DREAD(hd, eact_header)
hd.filesize = be32toh(hd.filesize);
hd.setup_area_size = be32toh(hd.setup_area_size);
hd.eact_version = be32toh(hd.eact_version);
hd.os_version = be32toh(hd.os_version);
DREAD(hd, g1m_eact_header_s)
hd.g1m_eact_header_filesize = be32toh(hd.g1m_eact_header_filesize);
hd.g1m_eact_header_setup_area_size = be32toh(hd.g1m_eact_header_setup_area_size);
hd.g1m_eact_header_eact_version = be32toh(hd.g1m_eact_header_eact_version);
hd.g1m_eact_header_os_version = be32toh(hd.g1m_eact_header_os_version);
/* find out the size of the setup area */
log_info("E-Activity version is '%s'.",
hd.eact_version == EACT_G1E ? "g1e" :
hd.eact_version == EACT_G2E ? "g2e" : "g3e");
hd.g1m_eact_header_eact_version == EACT_G1E ? "g1e" :
hd.g1m_eact_header_eact_version == EACT_G2E ? "g2e" : "g3e");
log_info("Setup area size is 0x%" PRIx32 " bytes long.",
hd.setup_area_size);
hd.g1m_eact_header_setup_area_size);
/* allocate handle */
*h = malloc(sizeof(g1m_handle_t));
@ -465,17 +469,17 @@ int g1m_decode_std_eact(g1m_handle_t **h, g1m_buffer_t *buffer,
memset(handle, 0, sizeof(g1m_handle_t));
/* skip the setup area */
SKIP(hd.setup_area_size)
SKIP(hd.g1m_eact_header_setup_area_size)
/* prepare the handle */
handle->g1m_handle_type = g1m_type_eact;
handle->g1m_handle_platform = g1m_platform_fx;
if (hd.eact_version == EACT_G3E) /* check if fx-CG */
if (hd.g1m_eact_header_eact_version == EACT_G3E) /* check if fx-CG */
handle->g1m_handle_platform = g1m_platform_cg;
/* get content buffer */
size_t bufsize = hd.filesize - sizeof(struct standard_header)
- sizeof(struct eact_header) - hd.setup_area_size;
size_t bufsize = hd.g1m_eact_header_filesize - sizeof(g1m_standard_header_t)
- sizeof(g1m_eact_header_t) - hd.g1m_eact_header_setup_area_size;
uint8_t buf[bufsize];
GREAD(&buf, bufsize)

View File

@ -73,16 +73,17 @@ static uint32_t **fkeydup3(uint8_t *fkey)
*/
int g1m_decode_std_fkey(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std)
g1m_standard_header_t *std)
{
int err; (void)std;
/* read the subheader */
DREAD(hd, g1n_subheader)
uint_fast16_t num = be16toh(hd.fkey_count) + 1;
DREAD(hd, g1m_fkey_subheader_s)
uint_fast16_t num = be16toh(hd.g1m_fkey_subheader_count) + 1;
/* beat the best! read the rest! */
size_t data_size = std->filesize - sizeof(struct standard_header)
- sizeof(struct g1n_subheader);
size_t data_size = be32toh(std->g1m_standard_header_filesize)
- sizeof(g1m_standard_header_t)
- sizeof(g1m_fkey_subheader_t);
uint8_t data[data_size];
READ(data, data_size)
@ -138,26 +139,27 @@ fail:
*/
int g1m_decode_std_cg_fkey(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std, struct standard_subheader *sub,
struct _prizm_subheader *prizm, uint32_t *check)
g1m_standard_header_t *std, g1m_standard_subheader_t *sub,
g1m_standard_prizm_subheader_t *prizm, uint32_t *check)
{
int err = g1m_error_alloc; uint8_t *data = NULL;
(void)std; (void)prizm;
/* read the subheader */
DREAD(lhd, g3l_lang_header)
*check = g1m_checksum32(&lhd, sizeof(struct g3l_lang_header), *check);
DREAD(lhd, g1m_prizm_lang_subheader_s)
*check = g1m_checksum32(&lhd, sizeof(g1m_prizm_lang_subheader_t), *check);
/* read the data */
size_t data_size = be32toh(sub->filesize) - sizeof(struct standard_header)
- sizeof(struct standard_subheader) - sizeof(struct _prizm_subheader)
- sizeof(struct g3l_lang_header) - 4;
size_t data_size = be32toh(sub->g1m_standard_subheader_filesize)
- sizeof(g1m_standard_header_t) - sizeof(g1m_standard_subheader_t)
- sizeof(g1m_standard_prizm_subheader_t)
- sizeof(g1m_prizm_lang_subheader_t) - 4;
if (!(data = malloc(data_size))) goto fail;
READ(data, data_size)
*check = g1m_checksum32(data, data_size, *check);
/* make the handle */
int num = be32toh(lhd.num);
int num = be32toh(lhd.g1m_prizm_lang_subheader_count);
err = g1m_make_fkey(h, g1m_platform_cg, num);
if (err) return (err);
g1m_handle_t *handle = *h;

View File

@ -31,20 +31,21 @@
*/
int g1m_decode_std_lang(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std)
g1m_standard_header_t *std)
{
(void)std; int err;
/* read the subheader */
DREAD(hd, g1l_subheader)
uint_fast16_t num = be16toh(hd.message_count) + 1;
DREAD(hd, g1m_lang_subheader_s)
uint_fast16_t num = be16toh(hd.g1m_lang_subheader_count) + 1;
/* log */
log_info("%" PRIuFAST16 " messages to read", num);
/* beat the best, read the rest! */
size_t data_size = std->filesize - sizeof(struct standard_header)
- sizeof(struct g1l_subheader);
size_t data_size = std->g1m_standard_header_filesize
- sizeof(g1m_standard_header_t)
- sizeof(g1m_lang_subheader_t);
uint8_t data[data_size];
READ(data, data_size)
@ -103,26 +104,28 @@ fail:
*/
int g1m_decode_std_cg_lang(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std, struct standard_subheader *sub,
struct _prizm_subheader *prizm, uint32_t *check)
g1m_standard_header_t *std, g1m_standard_subheader_t *sub,
g1m_standard_prizm_subheader_t *prizm, uint32_t *check)
{
int err = g1m_error_alloc; uint8_t *data = NULL;
(void)std; (void)prizm;
/* read the subheader */
DREAD(lhd, g3l_lang_header)
*check = g1m_checksum32(&lhd, sizeof(struct g3l_lang_header), *check);
DREAD(lhd, g1m_prizm_lang_subheader_s)
*check = g1m_checksum32(&lhd, sizeof(g1m_prizm_lang_subheader_t), *check);
/* read the data */
size_t data_size = be32toh(sub->filesize) - sizeof(struct standard_header)
- sizeof(struct standard_subheader) - sizeof(struct _prizm_subheader)
- sizeof(struct g3l_lang_header) - 4;
size_t data_size = be32toh(sub->g1m_standard_subheader_filesize)
- sizeof(g1m_standard_header_t)
- sizeof(g1m_standard_subheader_t)
- sizeof(g1m_standard_prizm_subheader_t)
- sizeof(g1m_lang_subheader_t) - 4;
if (!(data = malloc(data_size))) goto fail;
READ(data, data_size)
*check = g1m_checksum32(data, data_size, *check);
/* make the handle */
int num = be32toh(lhd.num);
int num = be32toh(lhd.g1m_prizm_lang_subheader_count);
err = g1m_make_lang(h, g1m_platform_cg, num);
if (err) return (err);
g1m_handle_t *handle = *h;

View File

@ -30,11 +30,11 @@
*/
int g1m_decode_std_mcs(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std)
g1m_standard_header_t *std)
{
int err = g1m_error_alloc;
/* get number of subparts from the standard header */
uint_fast16_t num = std->number;
uint_fast16_t num = std->g1m_standard_header_number;
uint_fast32_t i;
/* make the handle */
@ -46,32 +46,36 @@ int g1m_decode_std_mcs(g1m_handle_t **h, g1m_buffer_t *buffer,
log_info("%" PRIuFAST16 " total mcs files to browse", num);
for (handle->g1m_handle_count = 0; handle->g1m_handle_count < (int)num;) {
/* get the subheader */
GDREAD(hd, mcs_subheader)
GDREAD(hd, g1m_mcs_subheader_s)
/* correct endianess */
hd.subcount = be32toh(hd.subcount);
hd.g1m_mcs_subheader_subcount = be32toh(hd.g1m_mcs_subheader_subcount);
/* log info about part */
log_info("New group! Group name is '%.16s'.", hd.intname);
log_info("%d mcs files to browse in that group", hd.subcount);
log_info("New group! Group name is '%.16s'.",
hd.g1m_mcs_subheader_intname);
log_info("%d mcs files to browse in that group",
hd.g1m_mcs_subheader_subcount);
/* foreach subpart */
for (i = 0; i < hd.subcount; i++) {
for (i = 0; i < hd.g1m_mcs_subheader_subcount; i++) {
/* get the part header */
GDREAD(fhd, mcs_fileheader)
fhd.datalength = be32toh(fhd.datalength);
GDREAD(fhd, g1m_mcs_fileheader_s)
/* log info about the subpart */
log_info("[%" PRIuFAST32 "] directory name is '%.8s'",
i, fhd.dirname);
log_info("[%" PRIuFAST32 "] filename is '%.8s'", i, fhd.filename);
i, fhd.g1m_mcs_fileheader_dirname);
log_info("[%" PRIuFAST32 "] filename is '%.8s'", i,
fhd.g1m_mcs_fileheader_filename);
log_info("[%" PRIuFAST32 "] data length is %" PRIu32,
i, fhd.datalength);
i, fhd.g1m_mcs_fileheader_datalength);
/* decode the head */
g1m_mcshead_t head;
g1m_decode_mcsfile_head(&head, fhd.filetype, hd.intname,
fhd.dirname, fhd.filename, fhd.datalength);
g1m_decode_mcsfile_head(&head, fhd.g1m_mcs_fileheader_filetype,
hd.g1m_mcs_subheader_intname, fhd.g1m_mcs_fileheader_dirname,
fhd.g1m_mcs_fileheader_filename,
be32toh(fhd.g1m_mcs_fileheader_datalength));
/* decode */
handle->g1m_handle_files[handle->g1m_handle_count] = NULL;

View File

@ -37,7 +37,6 @@ static void g3p_deobfuscate(uint8_t *buf, size_t n)
*buf++ = (byte << 5) | (byte >> 3);
}
}
/* ************************************************************************** */
/* Prizm Picture decoding function */
/* ************************************************************************** */
@ -53,16 +52,18 @@ static void g3p_deobfuscate(uint8_t *buf, size_t n)
*/
int g1m_decode_std_g3p(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std, struct standard_picheader *pic)
g1m_standard_header_t *std, g1m_standard_picheader_t *pic)
{
int err; *h = NULL;
uint8_t *defbuf = NULL, *infbuf = NULL;
/* read the image header */
DREAD(ihd, g3p_subheader)
unsigned int width = be16toh(ihd.width), height = be16toh(ihd.height);
DREAD(ihd, g1m_prizm_picture_subheader_s)
unsigned int width = be16toh(ihd.g1m_prizm_picture_subheader_width);
unsigned int height = be16toh(ihd.g1m_prizm_picture_subheader_height);
log_info("Width: %upx, height: %upx", width, height);
g1m_pictureformat_t picfmt; uint16_t rawcol = be16toh(ihd.color_depth);
g1m_pictureformat_t picfmt;
uint16_t rawcol = be16toh(ihd.g1m_prizm_picture_subheader_color_depth);
const char *coldesc; switch (rawcol) {
case g3p_color_4bit: picfmt = g1m_pictureformat_4bit_code;
coldesc = "4-bit"; break;
@ -72,19 +73,20 @@ int g1m_decode_std_g3p(g1m_handle_t **h, g1m_buffer_t *buffer,
err = g1m_error_magic; goto fail;
}
log_info("Picture format: %s", coldesc);
int gen = be16toh(ihd.generator_id);
int gen = be16toh(ihd.g1m_prizm_picture_subheader_generator_id);
log_info("Generator ID: 0x%04X", gen);
log_info("-");
/* read deflated image */
size_t deflated_size = be32toh(ihd.data_size) - 6; /* FIXME: dangerous */
size_t deflated_size = be32toh(ihd.g1m_prizm_picture_subheader_data_size)
- 6; /* FIXME: dangerous */
log_info("Reading %" PRIuSIZE "B of deflated data", deflated_size);
err = g1m_error_alloc;
if (!(defbuf = malloc(deflated_size))) goto fail;
READ(defbuf, deflated_size)
/* unobfuscate if required */
if (std->obfuscated0) {
if (std->g1m_standard_header_obfuscated0) {
log_info("Is obfuscated, let's deobfuscate!");
g3p_deobfuscate(defbuf, deflated_size);
}
@ -109,7 +111,8 @@ int g1m_decode_std_g3p(g1m_handle_t **h, g1m_buffer_t *buffer,
/* check the checksum */
uint32_t checksum; READ(&checksum, sizeof(uint32_t))
if (std->obfuscated0) g3p_deobfuscate((void*)&checksum, sizeof(uint32_t));
if (std->g1m_standard_header_obfuscated0)
g3p_deobfuscate((void*)&checksum, sizeof(uint32_t));
checksum = be32toh(checksum);
uLong adl = adler32(0, infbuf, inflated_size);
if (adl != (uLong)checksum) {
@ -121,7 +124,8 @@ int g1m_decode_std_g3p(g1m_handle_t **h, g1m_buffer_t *buffer,
}
/* make the handle */
err = g1m_make_picture(h, ihd.width, ihd.height);
err = g1m_make_picture(h, ihd.g1m_prizm_picture_subheader_width,
ihd.g1m_prizm_picture_subheader_height);
if (err) goto fail;
g1m_handle_t *handle = *h;
@ -139,7 +143,6 @@ fail:
free(infbuf); free(defbuf);
return (err);
}
/* ************************************************************************** */
/* Classpad Picture decoding function */
/* ************************************************************************** */
@ -155,7 +158,7 @@ fail:
*/
int g1m_decode_std_c2p(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std, struct standard_picheader *pic)
g1m_standard_header_t *std, g1m_standard_picheader_t *pic)
{
(void)h; (void)buffer;
(void)std; (void)pic;

View File

@ -29,7 +29,7 @@
int g1m_announce_addin(g1m_handle_t *handle, size_t *size)
{
*size += sizeof(struct standard_header) + sizeof(struct g1a_subheader);
*size += sizeof(g1m_standard_header_t) + sizeof(g1m_addin_subheader_t);
*size += handle->g1m_handle_size;
return (0);
}
@ -49,31 +49,34 @@ int g1m_encode_addin(g1m_handle_t *handle, g1m_buffer_t *buffer)
/* make the StandardHeader up */
size_t filesize = 0; g1m_announce_addin(handle, &filesize);
struct standard_header std = {
.main_id = "USBPower",
.subtype = "\xF3\x00\x10\x00\x10\x00",
.filesize = htobe32((uint32_t)filesize),
.control = (filesize + 0x41) & 0xFF,
.control2 = (filesize + 0xB8) & 0xFF,
.number = 0xFFFF};
g1m_standard_header_t std = {
.g1m_standard_header_main_id = "USBPower",
.g1m_standard_header_subtype = "\xF3\x00\x10\x00\x10\x00",
.g1m_standard_header_filesize = htobe32((uint32_t)filesize),
.g1m_standard_header_control = (filesize + 0x41) & 0xFF,
.g1m_standard_header_control2 = (filesize + 0xB8) & 0xFF,
.g1m_standard_header_number = 0xFFFF};
/* reverse it and output it */
b = (void*)&std;
for (i = 0; i < sizeof(struct standard_header); i++) b[i] = ~b[i];
for (i = 0; i < sizeof(g1m_standard_header_t); i++) b[i] = ~b[i];
DWRITE(std)
/* make the add-in subheader up and output it */
filesize -= sizeof(struct standard_header);
struct g1a_subheader sub = {
.estrips_count = 0,
.filesize = htobe32(filesize)};
strncpy((char*)sub.title, handle->g1m_handle_title, 8);
strncpy((char*)sub.internal_name, handle->g1m_handle_intname, 8);
g1m_encode_version(&handle->g1m_handle_version, (char*)sub.version);
filesize -= sizeof(g1m_standard_header_t);
g1m_addin_subheader_t sub = {
.g1m_addin_subheader_estrips_count = 0,
.g1m_addin_subheader_filesize = htobe32(filesize)};
strncpy((char*)sub.g1m_addin_subheader_title,
handle->g1m_handle_title, 8);
strncpy((char*)sub.g1m_addin_subheader_internal_name,
handle->g1m_handle_intname, 8);
g1m_encode_version(&handle->g1m_handle_version,
(char*)sub.g1m_addin_subheader_version);
g1m_encode_date(&handle->g1m_handle_creation_date,
(char*)sub.creation_date);
(char*)sub.g1m_addin_subheader_creation_date);
g1m_encode_picture((const uint32_t**)handle->g1m_handle_icon_unsel,
g1m_pictureformat_1bit, sub.icon,
g1m_pictureformat_1bit, sub.g1m_addin_subheader_icon,
G1A_ICON_WIDTH, G1A_ICON_HEIGHT);
DWRITE(sub)

View File

@ -32,7 +32,7 @@ int g1m_announce_mcs_cells(const g1m_mcsfile_t *handle, size_t *sz)
unsigned int y, x;
size_t content_size = handle->g1m_mcsfile_head.g1m_mcshead_height
* handle->g1m_mcsfile_head.g1m_mcshead_width * sizeof(g1m_mcsbcd_t);
*sz += sizeof(struct mcs_cellsheader) + content_size;
*sz += sizeof(g1m_mcs_cellsheader_t) + content_size;
/* check if there's an imaginary part */
for (y = 0; y < handle->g1m_mcsfile_head.g1m_mcshead_height; y++)
@ -60,11 +60,13 @@ int g1m_announce_mcs_cells(const g1m_mcsfile_t *handle, size_t *sz)
int g1m_encode_mcs_cells(const g1m_mcsfile_t *handle, g1m_buffer_t *buffer)
{
unsigned int y, x;
struct mcs_cellsheader hd = {
.height = htobe16(handle->g1m_mcsfile_head.g1m_mcshead_height),
.width = (handle->g1m_mcsfile_head.g1m_mcshead_type & g1m_mcstype_list)
g1m_mcs_cellsheader_t hd = {
.g1m_mcs_cellsheader_height =
htobe16(handle->g1m_mcsfile_head.g1m_mcshead_height),
.g1m_mcs_cellsheader_width =
(handle->g1m_mcsfile_head.g1m_mcshead_type & g1m_mcstype_list)
? 1 : htobe16(handle->g1m_mcsfile_head.g1m_mcshead_width),
._undocumented = {0}};
.g1m_mcs_cellsheader__undocumented = {0}};
/* write the header */
DWRITE(hd)

View File

@ -29,7 +29,7 @@
int g1m_announce_mcs_program(const g1m_mcsfile_t *handle, size_t *sz)
{
*sz += sizeof(struct mcs_programheader)
*sz += sizeof(g1m_mcs_programheader_t)
+ handle->g1m_mcsfile_head.g1m_mcshead_size;
return (0);
}
@ -46,8 +46,9 @@ int g1m_announce_mcs_program(const g1m_mcsfile_t *handle, size_t *sz)
int g1m_encode_mcs_program(const g1m_mcsfile_t *handle, g1m_buffer_t *buffer)
{
/* write the header */
struct mcs_programheader hd = {};
memcpy(hd.password, handle->g1m_mcsfile_head.g1m_mcshead_password,
g1m_mcs_programheader_t hd = {};
memcpy(hd.g1m_mcs_programheader_password,
handle->g1m_mcsfile_head.g1m_mcshead_password,
strlen(handle->g1m_mcsfile_head.g1m_mcshead_password));
DWRITE(hd)

View File

@ -50,7 +50,7 @@ struct ext_corresp {
#define ETERM {NULL}
static struct ext_corresp apps[] = {
/* CFX-9850G headers (very first headers with this extension system?) */
{casdyn_ext_9850, g1m_mcsinfo_cas50, (struct app_corresp[]){
{g1m_casdyn_ext_9850, g1m_mcsinfo_cas50, (struct app_corresp[]){
{"TXT"}, /* editor */
{"VAL"}, /* RUN? */
{"IMG"}, /* screen shooter? */
@ -59,14 +59,14 @@ static struct ext_corresp apps[] = {
}},
/* CFX-9850G header alias, used with the END packet only */
{casdyn_ext_end, g1m_mcsinfo_cas50, (struct app_corresp[]){
{g1m_casdyn_ext_end, g1m_mcsinfo_cas50, (struct app_corresp[]){
{"END"}, /* end packet... used in the same period than 9850G packets? */
ETERM
}},
/* Graph 100 (Algebra FX) headers */
{casdyn_ext_g100, g1m_mcsinfo_cas100, (struct app_corresp[]){
{g1m_casdyn_ext_g100, g1m_mcsinfo_cas100, (struct app_corresp[]){
{"MDL"}, /* Model, initialize */
{"END"}, /* Terminate */
{"REQ"}, /* Receive */
@ -80,7 +80,7 @@ static struct ext_corresp apps[] = {
}},
/* Graph 100 (Algebra FX) alternate headers */
{casdyn_ext_g100b, g1m_mcsinfo_cas100, (struct app_corresp[]){
{g1m_casdyn_ext_g100b, g1m_mcsinfo_cas100, (struct app_corresp[]){
{"ADN"}, /* Send (bis) */
{"REQ"}, /* Request (bis) */