272 lines
6.5 KiB
C
272 lines
6.5 KiB
C
/* ************************************************************************** */
|
|
/* _____ _ */
|
|
/* parse/mcs.c |_ _|__ _ _| |__ ___ _ _ */
|
|
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
|
/* | | (_) | |_| | | | | __/ |_| | */
|
|
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
|
/* Last updated: 2016/11/02 14:47:49 |___/ */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
#include <libg1m/internals.h>
|
|
|
|
/**
|
|
* g1m_parse_mcs_program:
|
|
* Parse a program.
|
|
*
|
|
* @arg handle the handle.
|
|
* @arg stream the stream to parse from.
|
|
* @arg length the data length.
|
|
* @return the error code (0 if ok).
|
|
*/
|
|
|
|
static int g1m_parse_mcs_program(g1m_t *handle, FILE *stream,
|
|
uint_fast32_t length)
|
|
{
|
|
/* read header */
|
|
DREAD(hd, mcs_programheader)
|
|
|
|
/* print header data */
|
|
log_info("Program password is '%.8s'.", hd.password);
|
|
|
|
/* seek for what's left in the file */
|
|
SKIP(length - sizeof(struct mcs_programheader))
|
|
|
|
/* no error */
|
|
return (0);
|
|
}
|
|
|
|
/**
|
|
* g1m_parse_mcs_spreadsheet:
|
|
* Parse a spreadsheet.
|
|
*
|
|
* @arg handle the handle.
|
|
* @arg stream the stream to parse from.
|
|
* @return the error code (0 if ok).
|
|
*/
|
|
|
|
static int g1m_parse_mcs_spreadsheet(g1m_t *handle, FILE *stream)
|
|
{
|
|
/* read header */
|
|
DREAD(hd, mcs_spreadsheetheader)
|
|
|
|
/* correct endianess */
|
|
uint_fast32_t colcount = be32toh(hd.column_count << 8);
|
|
hd.defs_size = be32toh(hd.defs_size);
|
|
|
|
/* log some info */
|
|
log_info("%ld columns to parse!", colcount);
|
|
|
|
/* get the column directory */
|
|
uint32_t column_directory[colcount];
|
|
READ(&column_directory, sizeof(uint32_t) * colcount)
|
|
/* - we should use `be32toh` here, but it isn't necessary for bool check. */
|
|
|
|
/* browse columns */
|
|
for (uint_fast32_t c = 0; c < colcount; c++) {
|
|
/* check if column is empty */
|
|
if (!column_directory[c])
|
|
continue;
|
|
|
|
/* get the row directory */
|
|
uint8_t row_directory[0x80];
|
|
READ(&row_directory, (size_t)0x80)
|
|
|
|
/* initialize loop values */
|
|
uint8_t *rd = row_directory;
|
|
int bit = 1 << 7;
|
|
|
|
/* explore each cell */
|
|
for (uint_fast32_t i = 0; i < 1000; i++) {
|
|
/* check if used */
|
|
if (*rd & bit) {
|
|
/* get cell */
|
|
DREAD(cell, bcd)
|
|
|
|
/* log it */
|
|
log_info("[%ld, %ld] not empty.", c, i);
|
|
}
|
|
|
|
/* iterate bit and rd */
|
|
rd += (bit & 1);
|
|
bit = (bit >> 1) | ((bit & 1) << 7);
|
|
}
|
|
}
|
|
|
|
/* no error */
|
|
return (0);
|
|
}
|
|
|
|
/**
|
|
* g1m_parse_mcs_list:
|
|
* Parse an List.
|
|
*
|
|
* @arg handle the handle.
|
|
* @arg stream the stream to parse from.
|
|
* @arg size the
|
|
* @return the error code (0 if ok).
|
|
*/
|
|
|
|
static int g1m_parse_mcs_list(g1m_t *handle, FILE *stream, uint_fast32_t size)
|
|
{
|
|
/* read header */
|
|
DREAD(hd, mcs_listheader)
|
|
|
|
/* correct endianess */
|
|
uint16_t elcount = hd.element_count;
|
|
elcount = be16toh(elcount);
|
|
|
|
/* prepare browsing */
|
|
size -= sizeof(struct mcs_listheader);
|
|
size_t elsize = sizeof(struct bcd) * elcount;
|
|
|
|
/* make tabs */
|
|
struct bcd real[elcount];
|
|
struct bcd imgn[elcount];
|
|
bzero(real, elsize);
|
|
bzero(imgn, elsize);
|
|
|
|
/* browse */
|
|
log_info("Browsing %d list elements", elcount);
|
|
READ(&real, elsize)
|
|
if (size > elsize) /* FIXME: HACK */
|
|
READ(&imgn, elsize)
|
|
|
|
/* no error */
|
|
return (0);
|
|
}
|
|
|
|
/**
|
|
* g1m_parse_mcs_mat:
|
|
* Parse a Matrix.
|
|
*
|
|
* @arg handle the handle.
|
|
* @arg stream the stream to parse from.
|
|
* @return the error code (0 if ok).
|
|
*/
|
|
|
|
static int g1m_parse_mcs_mat(g1m_t *handle, FILE *stream)
|
|
{
|
|
/* read header */
|
|
DREAD(hd, mcs_matheader)
|
|
|
|
/* correct endianess */
|
|
hd.width = be16toh(hd.width);
|
|
hd.height = be16toh(hd.height);
|
|
|
|
/* log info */
|
|
log_info("Matrix is %d/%d", hd.width, hd.height);
|
|
|
|
/* parse cells */
|
|
size_t num = hd.width * hd.height;
|
|
for (size_t i = 0; i < num; i++) {
|
|
/* read the cell */
|
|
DREAD(cell, bcd)
|
|
|
|
/* get x using `i % height` and y using `i / height` */
|
|
}
|
|
|
|
/* no error */
|
|
return (0);
|
|
}
|
|
|
|
/**
|
|
* g1m_parse_mcs_capture:
|
|
* Parse a capture.
|
|
*
|
|
* @arg handle the handle.
|
|
* @arg stream the stream to parse from.
|
|
* @return the error code (0 if ok).
|
|
*/
|
|
|
|
static int g1m_parse_mcs_capture(g1m_t *handle, FILE *stream)
|
|
{
|
|
/* read header */
|
|
DREAD(hd, mcs_captureheader)
|
|
|
|
/* correct endianess */
|
|
hd.width = be16toh(hd.width);
|
|
hd.height = be16toh(hd.height);
|
|
|
|
/* print info */
|
|
log_info("capture is %ux%u sized", hd.width, hd.height);
|
|
|
|
/* skip */
|
|
SKIP(hd.height * (hd.width / 8 + !!(hd.width % 8)))
|
|
|
|
/* no error */
|
|
return (0);
|
|
}
|
|
|
|
/**
|
|
* g1m_parse_mcs:
|
|
* We have passed the Standard Header and it's a g... MCS! Let's parse it!
|
|
*
|
|
* @arg handle the handle.
|
|
* @arg stream the stream to parse from.
|
|
* @arg num number of sizes.
|
|
* @return the error code (0 if ok).
|
|
*/
|
|
|
|
int g1m_parse_mcs(g1m_t *handle, FILE *stream, uint_fast16_t num)
|
|
{
|
|
log_info("%ld parts to browse", num);
|
|
|
|
/* read all of the parts */
|
|
for (uint_fast16_t i = 0; i < num; i++) {
|
|
/* get the subheader */
|
|
DREAD(hd, mcs_subheader)
|
|
|
|
/* correct endianess */
|
|
hd.subcount = be32toh(hd.subcount);
|
|
|
|
/* log info about part */
|
|
log_info("[%ld] Internal name is '%.16s'", i, hd.intname);
|
|
log_info("[%ld] %d subparts to browse", i, hd.subcount);
|
|
|
|
/* foreach subpart */
|
|
uint_fast32_t subcount = hd.subcount;
|
|
for (uint_fast32_t j = 0; j < subcount; j++) {
|
|
/* get the part header */
|
|
DREAD(phd, mcs_partheader)
|
|
|
|
/* correct endianess */
|
|
phd.datalength = be32toh(phd.datalength);
|
|
|
|
/* log info about the subpart */
|
|
log_info("[%ld,%ld] directory name is '%.8s'", i, j, phd.dirname);
|
|
log_info("[%ld,%ld] filename is '%.8s'", i, j, phd.filename);
|
|
log_info("[%ld,%ld] directory type is '%s' (0x%02d)",
|
|
i, j, g1m_get_dtype_string(phd.dirtype), phd.dirtype);
|
|
log_info("[%ld,%ld] data length is %u", i, j, phd.datalength);
|
|
|
|
/* and read that much data */
|
|
int err = 0;
|
|
switch (phd.dirtype) {
|
|
case mcs_dtype_program:
|
|
err = g1m_parse_mcs_program(handle, stream, phd.datalength);
|
|
break;
|
|
case mcs_dtype_spreadsheet:
|
|
err = g1m_parse_mcs_spreadsheet(handle, stream);
|
|
break;
|
|
case mcs_dtype_capture:
|
|
err = g1m_parse_mcs_capture(handle, stream);
|
|
break;
|
|
case mcs_dtype_list:
|
|
err = g1m_parse_mcs_list(handle, stream, phd.datalength);
|
|
break;
|
|
case mcs_dtype_mat:
|
|
err = g1m_parse_mcs_mat(handle, stream);
|
|
break;
|
|
default:
|
|
SKIP(phd.datalength)
|
|
}
|
|
|
|
/* if there is an error, return it */
|
|
if (err) return (err);
|
|
}
|
|
}
|
|
|
|
/* no error */
|
|
return (0);
|
|
}
|