cake
/
libg1m
Archived
1
0
Fork 0
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libg1m/src/parse/mcs.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);
}