Implemented matrixes and correct CAS type decoding.
This commit is contained in:
parent
795c9638c6
commit
a3d708c766
|
@ -55,7 +55,7 @@ struct caspro_header {
|
|||
};
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Variable/number */
|
||||
/* Variable */
|
||||
/* ************************************************************************** */
|
||||
/* Variable has the following structure (described in a comment):
|
||||
*
|
||||
|
@ -73,6 +73,26 @@ struct caspro_header {
|
|||
*
|
||||
* uint8_t checksum;
|
||||
* The checksum (calculated as for the header). */
|
||||
/* ************************************************************************** */
|
||||
/* Matrix/List */
|
||||
/* ************************************************************************** */
|
||||
/* The matrix height is stored in `used`, and its width is stored in the low
|
||||
* byte of `length`. For the list, only the height is used (`used`).
|
||||
*
|
||||
* There aren't any imaginary parts in matrixes and lists (and this wasn't made
|
||||
* possible until CASIOWIN 2.00, so a long time after). Each value (line by
|
||||
* line) is sent as an independent cell, which has this format: */
|
||||
|
||||
struct caspro_cell {
|
||||
/* coordinates */
|
||||
uint16_t y, x;
|
||||
|
||||
/* the value */
|
||||
cas_bcd_t val;
|
||||
|
||||
/* the checksum */
|
||||
uint8_t checksum;
|
||||
};
|
||||
|
||||
/* TODO: other file formats */
|
||||
# pragma pack()
|
||||
|
|
|
@ -153,6 +153,7 @@ int g1m_decode_cashpart_##NAME(g1m_mcshead_t *head, g1m_mcshead_t *heads, \
|
|||
G1M_CASFUNC(var)
|
||||
G1M_CASFUNC(program)
|
||||
G1M_CASHFUNC(program)
|
||||
G1M_CASFUNC(matrix)
|
||||
/* ************************************************************************** */
|
||||
/* Picture utilities */
|
||||
/* ************************************************************************** */
|
||||
|
|
|
@ -82,6 +82,7 @@ typedef struct g1m_mcs_cell_s {
|
|||
/* mcs file head flags */
|
||||
# define g1m_mcsflag_unfinished 0x8000 /* is there still parts to read? */
|
||||
# define g1m_mcsflag_multiple 0x4000 /* is a group */
|
||||
# define g1m_mcsflag_request 0x2000 /* is a request */
|
||||
# define g1m_mcsflag_complex 0x0001 /* is a complex variable */
|
||||
|
||||
/* mcs file type -- what type of raw information is there
|
||||
|
@ -110,7 +111,7 @@ typedef struct g1m_mcshead_s {
|
|||
unsigned char _group[17], _dirname[9];
|
||||
|
||||
/* cas-related raw data */
|
||||
unsigned char _maintype[4];
|
||||
unsigned char _appname[4];
|
||||
unsigned char _datatype[3];
|
||||
|
||||
/* the program password */
|
||||
|
|
|
@ -47,6 +47,8 @@ struct cas_corresp {
|
|||
static struct cas_corresp cas_types[] = {
|
||||
{g1m_mcstype_var, FUNC(var), NULL},
|
||||
{g1m_mcstype_program, FUNC(program), HFUNC(program)},
|
||||
{g1m_mcstype_matrix, FUNC(matrix), NULL},
|
||||
{g1m_mcstype_list, FUNC(matrix), NULL},
|
||||
TTERM
|
||||
};
|
||||
|
||||
|
@ -115,6 +117,14 @@ static int decode_caspro_head(g1m_mcshead_t *head, struct caspro_header *hd)
|
|||
/* TODO: id */
|
||||
head->count = 1;
|
||||
break;
|
||||
case g1m_mcstype_matrix:
|
||||
head->height = hd->used;
|
||||
head->width = be16toh(hd->length) & 0xFF;
|
||||
break;
|
||||
case g1m_mcstype_list:
|
||||
head->height = hd->used;
|
||||
head->width = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
|
|
|
@ -104,3 +104,41 @@ fail:
|
|||
*handle = NULL;
|
||||
return (err);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_decode_caspart_matrix:
|
||||
* Decode a CAS matrix part.
|
||||
*
|
||||
* @arg handle the handle to contribute to.
|
||||
* @arg buffer the buffer to read from.
|
||||
* @return the error code (0 if ok).
|
||||
*/
|
||||
|
||||
int g1m_decode_caspart_matrix(g1m_mcsfile_t *handle, g1m_buffer_t *buffer)
|
||||
{
|
||||
/* get content */
|
||||
DREAD(cell, caspro_cell)
|
||||
|
||||
/* check the cell */
|
||||
uint8_t csum = ~g1m_checksum8(&cell, sizeof(struct caspro_cell) - 1) + 1;
|
||||
if (csum != cell.checksum)
|
||||
return (g1m_error_checksum);
|
||||
|
||||
/* decode */
|
||||
cell.y = be16toh(cell.y);
|
||||
cell.x = be16toh(cell.x);
|
||||
g1m_bcd_t bcd; g1m_bcd_fromcas(&cell.val, &bcd);
|
||||
handle->cells[cell.y][cell.x] = (g1m_mcs_cell_t){
|
||||
.real = bcd,
|
||||
.imgn = {},
|
||||
.used = 1
|
||||
};
|
||||
|
||||
/* check if its the last cell */
|
||||
if (cell.y == handle->head.height - 1
|
||||
&& cell.x == handle->head.width - 1)
|
||||
handle->head.flags &= ~g1m_mcsflag_unfinished;
|
||||
|
||||
/* no error! */
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -41,8 +41,12 @@ struct type_corresp {
|
|||
#define TTERM {NULL, 0, 0}
|
||||
static struct type_corresp cas_groups[] = {
|
||||
/* implemented */
|
||||
{"LT", g1m_mcstype_list, 0}, // list
|
||||
{"MT", g1m_mcstype_matrix, 0}, // matrix
|
||||
{"P1", g1m_mcstype_program, 0}, // one program
|
||||
{"PG", g1m_mcstype_program, 0}, // same than above
|
||||
{"PZ", g1m_mcstype_program, g1m_mcsflag_multiple}, // set of programs
|
||||
{"VM", g1m_mcstype_variable, 0}, // one variable
|
||||
|
||||
/* not implemented yet */
|
||||
{"AA", 0, 0}, // dynamic graph functions
|
||||
|
@ -54,18 +58,26 @@ static struct type_corresp cas_groups[] = {
|
|||
{"DD", 0, 0}, // screenshot
|
||||
{"EN", 0, 0}, // one editor file
|
||||
{"FN", 0, 0}, // set of editor files
|
||||
{"FT", 0, 0}, // ??? (cafix)
|
||||
{"F1", 0, 0}, // one function memory
|
||||
{"F6", 0, 0}, // set of function memories
|
||||
{"GA", 0, 0}, // set of graph functions
|
||||
{"GF", 0, 0}, // graph zoom factor (graph function?)
|
||||
{"GM", 0, 0}, // gmem (cafix)
|
||||
{"GR", 0, 0}, // graph range
|
||||
{"GT", 0, 0}, // function table
|
||||
{"MA", 0, 0}, // set of matrices
|
||||
{"PC", 0, 0}, // picture from 9xxx (cafix)
|
||||
{"PD", 0, 0}, // polynomial equations
|
||||
{"RF", 0, 0}, // ??? (cafix)
|
||||
{"RR", 0, 0}, // ??? (cafix)
|
||||
{"RT", 0, 0}, // recursion table
|
||||
{"SD", 0, 0}, // simultaneous equations
|
||||
{"SE", 0, 0}, // equation (cafix)
|
||||
{"SR", 0, 0}, // linear regression data
|
||||
{"SS", 0, 0}, // standard deviation data
|
||||
{"TR", 0, 0}, // ??? (cafix)
|
||||
{"WD", 0, 0}, // window data (cafix)
|
||||
|
||||
/* terminating entry */
|
||||
TTERM
|
||||
|
|
|
@ -22,13 +22,15 @@
|
|||
/* Local types */
|
||||
/* ************************************************************************** */
|
||||
/* Correspondance type */
|
||||
struct type_corresp {
|
||||
#define flg_type 0x0001 /* if not there, the type is defined by the datatype */
|
||||
#define flg_flags 0x0002 /* the following value is the flag to OR. */
|
||||
struct app_corresp {
|
||||
/* identification */
|
||||
const char *maintype;
|
||||
const char *datatype;
|
||||
const char *name;
|
||||
|
||||
/* libg1m MCS file type */
|
||||
g1m_mcstype_t type;
|
||||
/* values */
|
||||
unsigned int flags; /* the internal flags */
|
||||
unsigned long int value; /* meaning of this depends on the flags */
|
||||
};
|
||||
|
||||
/* ************************************************************************** */
|
||||
|
@ -38,12 +40,12 @@ struct type_corresp {
|
|||
* - Correspondances with a NULL data type means the data type isn't to be
|
||||
* read. */
|
||||
|
||||
#define TTERM {NULL, NULL, 0}
|
||||
static struct type_corresp cas_types[] = {
|
||||
{"TXT", "PG", g1m_mcstype_program},
|
||||
{"VAL", "VM", g1m_mcstype_variable},
|
||||
{"END", NULL, g1m_mcstype_end},
|
||||
//{"VAL", "MT", g1m_mcstype_matrix},
|
||||
#define TTERM {NULL, 0, 0}
|
||||
static struct app_corresp apps[] = {
|
||||
{"TXT", 0, 0}, /* editor */
|
||||
{"VAL", 0, 0}, /* RUN? */
|
||||
{"REQ", flg_flags, g1m_mcsflag_request}, /* request */
|
||||
{"END", flg_type, g1m_mcstype_end}, /* end */
|
||||
|
||||
/* terminating entry */
|
||||
TTERM
|
||||
|
@ -57,38 +59,44 @@ static struct type_corresp cas_types[] = {
|
|||
* Get the libg1m MCS type from raw CAS identification data.
|
||||
*
|
||||
* @arg head the head to fill.
|
||||
* @arg maintype the main type string.
|
||||
* @arg app the app string.
|
||||
* @arg datatype the data type string.
|
||||
* @return the error (if any).
|
||||
*/
|
||||
|
||||
int g1m_maketype_caspro(g1m_mcshead_t *head,
|
||||
const char *maintype, const char *datatype)
|
||||
const char *app, const char *datatype)
|
||||
{
|
||||
/* copy raw information */
|
||||
memset(head, 0, sizeof(g1m_mcshead_t));
|
||||
head->flags |= g1m_mcsinfo_caspro;
|
||||
memcpy(head->_maintype, maintype, 3);
|
||||
head->_maintype[3] = 0;
|
||||
memcpy(head->_datatype, datatype, 2);
|
||||
head->_datatype[2] = 0;
|
||||
|
||||
/* look for correspondance */
|
||||
struct type_corresp *c;
|
||||
for (c = cas_types; c->datatype; c++) {
|
||||
if ((!c->maintype || !strncmp(maintype, c->maintype, 4))
|
||||
&& (!c->datatype || !strncmp(datatype, c->datatype, 3)))
|
||||
/* look for the app */
|
||||
struct app_corresp *a;
|
||||
for (a = apps; a->name; a++) {
|
||||
if (!strncmp(a->name, app, 3))
|
||||
break;
|
||||
}
|
||||
if (!c->maintype) goto notfound;
|
||||
if (!a->name) goto notfound;
|
||||
|
||||
/* check if we need the datatype */
|
||||
if (a->flags & flg_type) {
|
||||
memset(head, 0, sizeof(g1m_mcshead_t));
|
||||
head->type = a->value;
|
||||
memcpy(head->_appname, app, 3); head->_appname[3] = 0;
|
||||
} else {
|
||||
int err = g1m_maketype_cas(head, datatype);
|
||||
if (err) return (err);
|
||||
}
|
||||
|
||||
/* copy raw information */
|
||||
head->flags = (head->flags & ~g1m_mcsmask_info) | g1m_mcsinfo_caspro;
|
||||
memcpy(head->_appname, app, 3); head->_appname[3] = 0;
|
||||
if (a->flags & flg_flags)
|
||||
head->flags |= (unsigned int)a->value;
|
||||
|
||||
/* fill in info and return */
|
||||
head->type = c->type;
|
||||
return (0);
|
||||
|
||||
notfound:
|
||||
log_info("Type with '%.4s' data string was not implemented or not "
|
||||
"recognized.", datatype);
|
||||
log_info("Type with '%.3s' app name and '%.2s' data string was not"
|
||||
"implemented or recognized.", app, datatype);
|
||||
head->type = 0;
|
||||
return (1);
|
||||
}
|
||||
|
|
Reference in New Issue