Namespace for format headers.
This commit is contained in:
parent
264e8d5f66
commit
0db29bafb3
|
@ -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
|
||||
|
|
|
@ -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: */
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`. */
|
||||
/* ************************************************************************** */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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? */
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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) */
|
||||
|
||||
|
|
Reference in New Issue