cake
/
libg1m
Archived
1
0
Fork 0

I love e-activities. No, I do. Really.

This commit is contained in:
Thomas Touhey 2016-11-02 01:46:08 +01:00
parent 0f131384c2
commit 0233e77d04
5 changed files with 129 additions and 76 deletions

0
Makefile Normal file → Executable file
View File

0
Makefile.msg Normal file → Executable file
View File

0
Makefile.vars Normal file → Executable file
View File

View File

@ -368,12 +368,12 @@ struct mcs_matheader {
* E-Activities (g1e, g2e, g3e)
* -----------------------------------------------------------------------------
* E-Activities are the format CASIO uses for in-calc documents.
* It is the funniest subformat the the libg1m can parse.
*
* There is only one part for e-activities.
* This part is quite complicated. The header has three zones:
* The overall header has two zones:
* - the special header, that keeps the global info;
* - the setup area, that keeps part of the calculator setup;
* - the intermediate data, with magic things and line count.
* - the setup area, that keeps one part of the calculator setup.
*
* There are several types for E-Activies, identified by the extensions
* CASIO give them.
@ -406,38 +406,43 @@ struct eact_header {
uint32_t os_version;
};
/* Here, we won't put the setup directory, but we have to skip
* `0x04 + setup_directory_size` + (`setup_area_size` - 0x30) bytes.
* Parse the setup directory is TODO.
*
* The intermediate zone is full of control and magic bytes.
* The line count is not really part of it, but we'll bodge it here for
* simplicity: */
/* And now, the funniest part: the content.
* So a content has this header: */
struct eact_intermediate {
/* magic sequence: "@EACT" 0x00 0x00 0x00 0x00 0x00 0x00 0x01 */
uint8_t magic[12];
struct eact_contentheader {
/* content type: @EACT, @RUNMAT, ... */
uint8_t type[8];
/* control byte: `filesize` - 0x40 - `setup_area_size` */
uint32_t control;
/* magic sequence: 0x00 0x00 0x00 0x01 */
uint8_t magic[4];
/* magic sequence: "EACT1" 0x00 0x00 0x00 0x00 0x00 0x00 0x14 */
uint8_t magic2[12];
/* first length: simlo says `filesize` - 0x40 - `setup_area_size`
* i don't get what length is this... */
uint32_t length1;
/* control byte: `filesize` - 0x54 - `setup_area_size` */
uint32_t control2;
/* element name: "EACT1", "TEXT1", ... */
uint8_t name[12];
/* second length: simlo says `filesize` - 0x54 - `setup_area_size`
* i don't really get what length is this neither. */
uint32_t length2;
/* magic sequence: 0xD4 0x00 0x00 0x66 */
uint8_t magic3[4];
uint8_t magic2[4];
};
/* There are several types of contents.
* The most basic one is also called "@EACT".
* It has this content subheader: */
struct eact_eactheader {
/* line count */
uint32_t line_count;
};
/* Once this intermediate zone is passed, we have to parse the line directory,
* which is an array of `line_count` line descriptors.
*
* Each line has a type. Here are the known types: */
/* 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 {
eact_ltype_stdheading = 0x07,
@ -445,7 +450,7 @@ enum eact_linetype {
eact_ltype_code = 0x82
};
/* And here's the structure of a line descriptor: */
/* And here's the line descriptor structure: */
struct line_descriptor {
/* the entry type */
@ -455,9 +460,16 @@ struct line_descriptor {
uint32_t entry_offset :24;
};
/* Once this directory is passed, we have the array of lines.
* Each one is zero-terminated and 4-aligned by random filler bytes.
* -----------------------------------------------------------------------------
/* 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?
* Well, that's the funniest thing of E-Activities:
*
* they are RECURSIVE. [drama alert]
*
* Which means in each node, there can be a content to parse.
* TODO: find the link between line types and the @TYPES in
* the Content Header. */
/* -----------------------------------------------------------------------------
* fx-CG Pictures (g3p)
* -----------------------------------------------------------------------------
* These are pictures for fx-CG. They only have one part.

View File

@ -480,6 +480,82 @@ static int g1m_parse_g3p(g1m_t *handle, FILE *stream,
/* ************************************************************************** */
/* E-Activities */
/* ************************************************************************** */
/**
* g1m_parse_eact_content:
* Parse en EACT in an EACT.
*
* @arg handle the handle.
* @arg buf the buffer.
* @arg bufsize the buffer length.
* @return the error code (0 if ok).
*/
static int g1m_parse_eact_content(g1m_t *handle, uint8_t *buf, size_t bufsize)
{
/* read intermediate area */
struct eact_contentheader hd;
memcpy(&hd, buf, sizeof(struct eact_contentheader));
buf += sizeof(struct eact_contentheader);
bufsize -= sizeof(struct eact_contentheader);
/* correct endianess */
hd.length1 = be32toh(hd.length1);
hd.length2 = be32toh(hd.length2);
/* check magic sequences */
if (memcmp(hd.magic, "\x00\x00\x00\x01", 4)) {
log_info("First magic sequence is incorrect");
return (g1m_error_magic);
} else if (memcmp(hd.magic2, "\xD4\x00\x00\x66", 4)) {
log_info("Second magic sequence is incorrect");
return (g1m_error_magic);
}
/* log info */
log_info("Type is '%s'", hd.type);
log_info("Name is '%s'", hd.name);
/* get e-act subheader */
struct eact_eactheader ehd;
memcpy(&ehd, buf, sizeof(struct eact_eactheader));
/* correct endianess */
ehd.line_count = be32toh(ehd.line_count);
/* 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. */
struct line_descriptor *lds = (void*)&buf[sizeof(struct eact_eactheader)];
/* browse the lines */
if (ehd.line_count)
lds[0].entry_offset = be32toh(lds[0].entry_offset << 8);
for (uint_fast32_t i = 0; i < ehd.line_count; i++) {
/* get line size
* for this, we'll calculate the distance to the next line offset.
* 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;
else {
/* correct endianess of the next element */
lds[i + 1].entry_offset = be32toh(lds[i + 1].entry_offset << 8);
/* then calculate */
linesize = lds[i + 1].entry_offset - lds[i].entry_offset;
}
/* log data */
log_info("[%ld] Is '%s' (0x%02x)", i + 1,
g1m_get_eact_ltype_string(lds[i].entry_type), lds[i].entry_type);
log_info("[%ld] Buffer (0x%zxo) is:", i + 1, linesize);
logm_info(&buf[lds[i].entry_offset], linesize);
}
/* no errors */
return (0);
}
/**
* g1m_parse_eact:
* Parse an EACT.
@ -503,59 +579,24 @@ static int g1m_parse_eact(g1m_t * handle, FILE *stream)
hd.os_version = be32toh(hd.os_version);
/* find out the size of the setup area */
uint_fast32_t setup_directory_size = (hd.eact_version == EACT_G3E) ? 0x2C : 0x10;
uint_fast32_t setup_area_size = 0x04 + setup_directory_size
+ hd.setup_area_size - 0x30;
log_info("(Header) setup area size is 0x%x bytes long.",
log_info("E-Activity version is '%s'.",
hd.eact_version == EACT_G1E ? "g1e" :
hd.eact_version == EACT_G2E ? "g2e" : "g3e");
log_info("Setup area size is 0x%x bytes long.",
hd.setup_area_size);
log_info("(Calculation) setup area size is 0x%lx bytes long.",
setup_area_size);
/* skip the setup area */
SKIP(setup_area_size)
SKIP(hd.setup_area_size)
/* read intermediate area */
DREAD(in, eact_intermediate)
/* get content buffer */
size_t bufsize = hd.filesize - sizeof(struct eact_header)
- hd.setup_area_size;
log_info("bufsize is %zu", bufsize);
uint8_t buf[bufsize];
READ(&buf, bufsize)
/* correct endianess */
in.control = be32toh(in.control);
in.control2 = be32toh(in.control2);
in.line_count = be32toh(in.line_count);
/* check magic sequences and control numbers */
if (memcmp(in.magic, "@EACT\x00\x00\x00\x00\x00\x00\x01", 12)) {
log_info("First magic sequence is incorrect");
return (g1m_error_magic);
} else if (memcmp(in.magic2, "EACT1\x00\x00\x00\x00\x00\x00\x14", 12)) {
log_info("Second magic sequence is incorrect");
return (g1m_error_magic);
} else if (memcmp(in.magic3, "\xD4\x00\x00\x66", 4)) {
log_info("Third magic sequence is incorrect");
return (g1m_error_magic);
} else if (in.control != hd.filesize - 0x40 - hd.setup_area_size) {
log_info("First control number is incorrect");
return (g1m_error_magic);
} else if (in.control2 != hd.filesize - 0x54 - hd.setup_area_size) {
log_info("Second control number is incorrect");
return (g1m_error_magic);
}
/* browse the lines */
log_info("%d lines to browse.", in.line_count);
for (uint_fast32_t i = 0; i < in.line_count; i++) {
/* read the line descriptor */
DREAD(ld, line_descriptor)
/* correct endianess */
ld.entry_offset = be32toh(ld.entry_offset >> 8);
/* log info */
log_info("[%ld] Is '%s' (0x%02x)", i,
g1m_get_eact_ltype_string(ld.entry_type), ld.entry_type);
}
/* no errors */
return (0);
/* parse content */
return (g1m_parse_eact_content(handle, buf, bufsize));
}
/* ************************************************************************** */