diff --git a/include/libg1m/bcd.h b/include/libg1m/bcd.h index a50983f..28f777f 100644 --- a/include/libg1m/bcd.h +++ b/include/libg1m/bcd.h @@ -88,7 +88,7 @@ typedef struct g1m_bcd_s { # define g1m_casbcd_special 0x80 # define g1m_casbcd_negative 0x50 # define g1m_casbcd_pow_neg 0x01 -typedef struct { +typedef struct cas_bcd { unsigned char mantissa[8]; unsigned char signinfo; unsigned char exponent; diff --git a/include/libg1m/internals.h b/include/libg1m/internals.h index 5c7d281..e5ee168 100644 --- a/include/libg1m/internals.h +++ b/include/libg1m/internals.h @@ -118,7 +118,6 @@ G1M_STDFUNC(storage) /* others */ int g1m_decode_fkey_cg_content(g1m_t *handle, g1m_buffer_t *buffer, uint_fast32_t zonesize, uint32_t *pchecksum); - /* ************************************************************************** */ /* MCS-specific decoding functions */ /* ************************************************************************** */ @@ -135,7 +134,13 @@ G1M_MCSFUNC(program) G1M_MCSFUNC(setup) G1M_MCSFUNC(spreadsheet) G1M_MCSFUNC(string) +/* ************************************************************************** */ +/* CASPRO-specific decoding functions */ +/* ************************************************************************** */ +# define G1M_CASPROFUNC(NAME) \ +int g1m_decode_caspro_##NAME(g1m_mcsfile_t *handle, g1m_buffer_t *buffer); +G1M_CASPROFUNC(var) /* ************************************************************************** */ /* Picture utilities */ /* ************************************************************************** */ diff --git a/src/decode/caspro.c b/src/decode/caspro.c index d4eaee9..135acf2 100644 --- a/src/decode/caspro.c +++ b/src/decode/caspro.c @@ -20,6 +20,48 @@ * https://casetta.tuxfamily.org/formats/cas * ************************************************************************** */ #include +#define FUNC(NAME) g1m_decode_caspro_##NAME + +/* ************************************************************************** */ +/* Type correspondance list */ +/* ************************************************************************** */ +/* Part parsing function type */ +typedef int (*caspro_decode_function)(g1m_mcsfile_t*, g1m_buffer_t*); + +/* Correspondance type */ +struct caspro_corresp { + unsigned int type; + caspro_decode_function decode; +}; + +/* All correspondances */ +#define TTERM {0, NULL} +static struct caspro_corresp caspro_types[] = { + {g1m_mcstype_var, FUNC(var)}, + TTERM +}; + +/** + * lookup_caspro_decode: + * Lookup for a parsing function for the Caspro part. + * + * @arg type the libg1m MCS file type. + * @return the function (NULL if not found). + */ + +static caspro_decode_function lookup_caspro_decode(g1m_mcstype_t type) +{ + /* lookup for the type */ + struct caspro_corresp *c = caspro_types; + while (c->decode) { + if (type == c->type) + break; + c++; + } + + /* return the function */ + return (c->decode); +} /* ************************************************************************** */ /* Head decoding function */ @@ -42,12 +84,20 @@ int g1m_decode_caspro_head(g1m_mcshead_t *head, g1m_buffer_t *buffer) return (g1m_error_unknown); /* read specific data */ - if (head->type == g1m_mcstype_program) { + switch (head->type) { + case g1m_mcstype_program:; /* copy password */ char *endp = memchr(hd.aux, 0xFF, 8); size_t plen = endp ? (size_t)(endp - (char*)hd.aux) : 8; memcpy(head->password, hd.aux, plen); head->password[plen] = 0; + break; + case g1m_mcstype_variable: + /* TODO: id */ + head->count = 1; + if (hd.used) + head->flags |= g1m_mcsflag_unfinished; + break; } /* TODO */ @@ -61,15 +111,23 @@ int g1m_decode_caspro_head(g1m_mcshead_t *head, g1m_buffer_t *buffer) * g1m_decode_caspro_part: * Decode a CASIOLINK Protocol content part. * - * @arg file the file to make - * (or double pointer to the one to contribute to). - * @arg head the head to fill. + * @arg file the file to contribute to. * @arg buffer the buffer to read from. * @return if there was an error, or not. */ int g1m_decode_caspro_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer) { - /* TODO */ - return (g1m_error_unknown); + /* checks */ + if (!file) return (g1m_error_op); + + /* look for the decoding function */ + caspro_decode_function decode = lookup_caspro_decode(file->head.type); + if (!decode) { + log_error("No dedicated decoding function was found for this type!"); + return (g1m_error_unknown); + } + + /* decode the part */ + return ((*decode)(file, buffer)); } diff --git a/src/decode/mcs/var.c b/src/decode/mcs/var.c index c49c7ee..22d5726 100644 --- a/src/decode/mcs/var.c +++ b/src/decode/mcs/var.c @@ -53,3 +53,42 @@ int g1m_decode_mcs_var(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, /* no problem, woop woop */ return (0); } + +/** + * g1m_decode_caspro_var: + * Decode variable. + * + * @arg handle the handle to contribute to. + * @arg buffer the buffer to read from. + * @return the error code (0 if ok). + */ + +int g1m_decode_caspro_var(g1m_mcsfile_t *handle, g1m_buffer_t *buffer) +{ + /* read the magic and real part */ + uint8_t magic[4]; READ(magic, 4) + DREAD(rawreal, cas_bcd) + uint8_t csum = g1m_checksum8(magic, 4) + + g1m_checksum8(&rawreal, sizeof(cas_bcd_t)); + + /* read the imaginary part */ + g1m_bcd_t real, imgn = {}; + if (g1m_bcd_fromcas(&rawreal, &real)) { + DREAD(rawimgn, cas_bcd) + csum += g1m_checksum8(&rawimgn, sizeof(cas_bcd_t)); + g1m_bcd_fromcas(&rawimgn, &imgn); + } + + /* check the checksum */ + uint8_t checksum; READ(&checksum, 1) + if (csum != checksum) + return (g1m_error_checksum); + if (memcmp(magic, "\0\1\0\1", 4)) + return (g1m_error_magic); + + /* set the values and return */ + handle->var.real = real; + handle->var.imgn = imgn; + handle->head.flags &= ~g1m_mcsflag_unfinished; + return (0); +} diff --git a/src/decode/std/mcs.c b/src/decode/std/mcs.c index bb313d7..80e3f73 100644 --- a/src/decode/std/mcs.c +++ b/src/decode/std/mcs.c @@ -34,6 +34,7 @@ struct mcs_corresp { }; /* All correspondances */ +#define TTERM {0, NULL} static struct mcs_corresp mcs_types[] = { {g1m_mcstype_program, FUNC(program)}, {g1m_mcstype_list, FUNC(list)}, @@ -45,7 +46,8 @@ static struct mcs_corresp mcs_types[] = { {g1m_mcstype_string, FUNC(string)}, {g1m_mcstype_setup, FUNC(setup)}, {g1m_mcstype_alphamem, FUNC(var)}, - {} + {g1m_mcstype_variable, FUNC(var)}, + TTERM }; /** @@ -56,7 +58,7 @@ static struct mcs_corresp mcs_types[] = { * @return the function (NULL if not found). */ -static mcs_decode_func_t lookup_mcsfile_decode(unsigned int type) +static mcs_decode_func_t lookup_mcsfile_decode(g1m_mcstype_t type) { /* lookup for the type */ struct mcs_corresp *c = mcs_types; @@ -135,10 +137,10 @@ int g1m_decode_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *head, if (!head) return (g1m_error_op); g1m_mcshead_t h = *head; - /* look for the parsing function */ + /* look for the decoding function */ mcs_decode_func_t decode = lookup_mcsfile_decode(head->type); if (!decode) { - log_error("No dedicated parsing function for this type was found!"); + log_error("No dedicated decoding function for this type was found!"); goto notparsing; } diff --git a/src/manage/mcs.c b/src/manage/mcs.c index 308c312..c4d0396 100644 --- a/src/manage/mcs.c +++ b/src/manage/mcs.c @@ -58,7 +58,7 @@ int g1m_make_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *rawhead) h->cells[0] = malloc(sizeof(g1m_mcs_cell_t) * wd * ht); if (!h->cells[0]) { free(h->cells); goto fail; } - for (int y = 1; y < ht; y++) + for (unsigned int y = 1; y < ht; y++) h->cells[y] = &h->cells[0][h->head.width * y]; } break; diff --git a/src/type/caspro.c b/src/type/caspro.c index bbf0117..426441d 100644 --- a/src/type/caspro.c +++ b/src/type/caspro.c @@ -41,7 +41,8 @@ struct type_corresp { #define TTERM {NULL, NULL, 0} static struct type_corresp cas_types[] = { {"TXT", "PG", g1m_mcstype_program}, - {"VAL", "MT", g1m_mcstype_variable}, + {"VAL", "VM", g1m_mcstype_variable}, + //{"VAL", "MT", g1m_mcstype_matrix}, /* terminating entry */ TTERM