From 6c7ce4f45371415aa8d448498c68ecc83990de1f Mon Sep 17 00:00:00 2001 From: "Thomas \"Cakeisalie5\" Touhey" Date: Fri, 24 Mar 2017 02:04:48 +0100 Subject: [PATCH] Started adding things for CAS head making. --- include/libg1m.h | 9 +---- include/libg1m/format/cas.h | 4 +- include/libg1m/internals.h | 3 ++ include/libg1m/mcs.h | 6 ++- src/decode/cas.c | 1 - src/type/{caspro.c => cas/app.c} | 65 ++++++++++++++++++++++++------ src/type/{cas.c => cas/datatype.c} | 35 +++++++++++++++- 7 files changed, 97 insertions(+), 26 deletions(-) rename src/type/{caspro.c => cas/app.c} (68%) rename src/type/{cas.c => cas/datatype.c} (86%) diff --git a/include/libg1m.h b/include/libg1m.h index 97cc8ff..67dfaf2 100644 --- a/include/libg1m.h +++ b/include/libg1m.h @@ -135,17 +135,12 @@ extern int g1m_decode_mcsfile(g1m_mcsfile_t **handle, extern int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle, const g1m_mcshead_t *head, const unsigned char *data, size_t size); -/* open CAS head for decoding - * -------------------------- - * if the head corresponds to something you want as a file (e.g. - * not `g1m_mcstype_end`), then you should make the file using - * `g1m_make_mcsfile`, and call `g1m_decode_casfile_part` while the - * `g1m_mcsflag_unfinished` flag is set. - * Warning: there could be no parts to read! (e.g. unset variable) */ +/* open CAS head for decoding, correct it for encoding */ extern int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer); extern int g1m_decode_casfiles_part(g1m_mcshead_t *head, g1m_mcshead_t *heads, g1m_buffer_t *buffer); extern int g1m_decode_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer); +extern int g1m_correct_casfile_head(g1m_mcshead_t *head); /* ************************************************************************** */ /* MCS archive management */ /* ************************************************************************** */ diff --git a/include/libg1m/format/cas.h b/include/libg1m/format/cas.h index 920485e..bc3e1ef 100644 --- a/include/libg1m/format/cas.h +++ b/include/libg1m/format/cas.h @@ -110,8 +110,8 @@ struct cas50 { /* As you can guess, the two header formats are, in theory, incompatible. * In practice, anyhow, they more or less are: libg1m reads the first 7 bytes - * from the header, then tried to read a CAS50 header; if it doesn't manage, - * it uses CAS40 as a fallback. + * from the header, and tries to identify a CAS50 header; if it doesn't manage, + * it falls back on CAS40. * * Here are the content formats for the two header types: */ diff --git a/include/libg1m/internals.h b/include/libg1m/internals.h index c6d9c1d..064a36a 100644 --- a/include/libg1m/internals.h +++ b/include/libg1m/internals.h @@ -214,4 +214,7 @@ extern uint32_t g1m_checksum32(void *mem, size_t size, uint32_t checksum); /* Get extension */ extern int g1m_getext(const char *path, char *buf, size_t n); +/* Correct CAS head application */ +extern int g1m_correct_cashead_app(g1m_mcshead_t *head); + #endif /* LIBG1M_INTERNALS_H */ diff --git a/include/libg1m/mcs.h b/include/libg1m/mcs.h index 87a7cfe..4838411 100644 --- a/include/libg1m/mcs.h +++ b/include/libg1m/mcs.h @@ -93,8 +93,10 @@ typedef struct g1m_mcs_cell_s { # define g1m_mcsmask_info 0x0F00 # define g1m_mcsinfo_none 0x0000 # define g1m_mcsinfo_mcs 0x0100 -# define g1m_mcsinfo_cas 0x0200 -# define g1m_mcsinfo_caspro 0x0400 +# define g1m_mcsinfo_cas40 0x0200 +# define g1m_mcsinfo_cas g1m_mcsinfo_cas40 +# define g1m_mcsinfo_cas50 0x0400 +# define g1m_mcsinfo_caspro g1m_mcsinfo_cas50 /* mcs file content flags */ # define g1m_mcsflag_complex 0x0001 /* is a complex variable */ diff --git a/src/decode/cas.c b/src/decode/cas.c index 0a2ddd4..e3f0575 100644 --- a/src/decode/cas.c +++ b/src/decode/cas.c @@ -115,7 +115,6 @@ static int decode_caspro_head(g1m_mcshead_t *head, struct cas50 *hd) log_info("Is a program of %" PRIuFAST32 " bytes", head->size); break; case g1m_mcstype_variable: - /* TODO: id */ case g1m_mcstype_matrix: case g1m_mcstype_list: head->height = be16toh(hd->height) & 0xFF; diff --git a/src/type/caspro.c b/src/type/cas/app.c similarity index 68% rename from src/type/caspro.c rename to src/type/cas/app.c index 182b2de..e912e3f 100644 --- a/src/type/caspro.c +++ b/src/type/cas/app.c @@ -1,5 +1,5 @@ /* ***************************************************************************** - * type/caspro.c -- get the newer CAS type out of raw identification data. + * type/cas/app.c -- get the CAS app out of raw identification data. * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey * * This file is part of libg1m. @@ -23,7 +23,7 @@ /* ************************************************************************** */ /* Correspondance type */ #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. */ +#define flg_flags 0x0002 /* the following value is the flag to OR. */ struct app_corresp { /* identification */ const char *name; @@ -31,25 +31,31 @@ struct app_corresp { /* values */ unsigned int flags; /* the internal flags */ unsigned long int value; /* meaning of this depends on the flags */ + const char **datatypes; /* datatypes the app is used with */ }; /* ************************************************************************** */ /* Correspondances */ /* ************************************************************************** */ -/* All correspondances. Remarks: +/* App correspondances. Remarks: * - Correspondances with a NULL data type means the data type isn't to be * read. */ -#define TTERM {NULL, 0, 0} +#define BASIC(S, ...) {S, 0, 0, (const char*[]){__VA_ARGS__, NULL}} +#define FLAGS(S, F) {S, flg_flags, F, NULL} +#define TYPE(S, T) {S, flg_type, T, NULL} static struct app_corresp apps[] = { - {"TXT", 0, 0}, /* editor */ - {"VAL", 0, 0}, /* RUN? */ - {"IMG", 0, 0}, /* picture */ - {"REQ", flg_flags, g1m_mcsflag_request}, /* request */ - {"END", flg_type, g1m_mcstype_end}, /* end */ + /* advanced apps */ + FLAGS("REQ", g1m_mcsflag_request), /* request! */ + TYPE("END", g1m_mcstype_end), /* end packet */ - /* terminating entry */ - TTERM + /* basic apps */ + BASIC("TXT", "PG"), /* editor */ + BASIC("VAL", "VM"), /* RUN? */ + BASIC("IMG", "PC"), /* screen shooter? */ + + /* sentinel */ + {NULL, 0, 0, NULL} }; /* ************************************************************************** */ @@ -57,7 +63,7 @@ static struct app_corresp apps[] = { /* ************************************************************************** */ /** * g1m_maketype_caspro: - * Get the libg1m MCS type from raw CAS identification data. + * Get the CAS application from raw CAS50 identification data. * * @arg head the head to fill. * @arg app the app string. @@ -101,3 +107,38 @@ notfound: head->type = 0; return (1); } + +/** + * g1m_correct_cashead_app: + * Get the app string from data. + * + * @arg head the head to correct. + * @return if everything went alright. + */ + +int g1m_correct_cashead_app(g1m_mcshead_t *head) +{ + /* find the corresponding app correspondance */ + struct app_corresp *a; + for (a = apps; a->name; a++) { + if (a->flags & flg_type) { + if (a->value == head->type) + goto found; + } else if (a->flags & flg_flags) { + if ((head->flags & a->value) == a->value) + goto found; + } else /* if (!a->flags) */ { + const char **ds = a->datatypes - 1; + while (*++ds) if (!memcmp(*ds, head->_datatype, 2)) + goto found; + } + } + + /* app was not found. */ + return (g1m_error_unknown); + + /* app was found! */ +found: + memcpy(head->_appname, a->name, 4); + return (0); +} diff --git a/src/type/cas.c b/src/type/cas/datatype.c similarity index 86% rename from src/type/cas.c rename to src/type/cas/datatype.c index 44d42c9..dc34eff 100644 --- a/src/type/cas.c +++ b/src/type/cas/datatype.c @@ -1,5 +1,5 @@ /* ***************************************************************************** - * type/cas.c -- get the CAS type and data types out of raw identification data. + * type/cas/datatype.c -- get the CAS type out of raw identification data. * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey * * This file is part of libg1m. @@ -54,6 +54,7 @@ static struct type_corresp cas_groups[] = { BASIC("MT", g1m_mcstype_matrix), BASIC("PG", g1m_mcstype_program), BASIC("VM", g1m_mcstype_variable), + BASIC("\xFF\xFF", g1m_mcstype_end), /* programs */ {"P", arg | arg_is_num, g1m_mcstype_program, 0}, @@ -120,7 +121,7 @@ static int get_number(const char *s, int *num) /** * g1m_maketype_cas: - * Get the libg1m MCS type from raw CAS identification data. + * Get the libg1m MCS type from raw CAS40/CAS50 data type identification data. * * @arg head the head to fill. * @arg datatype the data type string (2 bytes long). @@ -161,3 +162,33 @@ notfound: head->type = 0; return (1); } + +/** + * g1m_correct_casfile_head: + * Correct a CAS file head. + * + * @arg head the head to correct. + * @return the error (0 if ok). + */ + +int g1m_correct_casfile_head(g1m_mcshead_t *head) +{ + /* look for correspondance */ + struct type_corresp *c = cas_groups - 1; + while ((++c)->type) { + if (head->type == c->type) /* FIXME: picture format? */ + goto found; + break; + } + + /* not found :( */ + return (g1m_error_unknown); + + /* found :) */ +found: + memcpy(head->_datatype, c->datatype, 2); + /* TODO: things with IDs, etc */ + if (g1m_mcsinfo(head) == g1m_mcsinfo_cas50) + return (g1m_correct_cashead_app(head)); + return (0); +}