diff --git a/AUTHORS.md b/AUTHORS.md index 61eabd2..0195d6a 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -2,9 +2,19 @@ Copyright (C) 2017 Thomas "Cakeisalie5" Touhey The documentation comes from a lot of places in the CASIO community, but mainly -from **Casiopeia** (mainly with Simon Lothar's documentation), **Cemetech** -(Prizm-related formats) and the **Casetta project documentation** -(reunion of five to twenty years old documentation). +from **Casiopeia**, **Cemetech** (Prizm-related), the **Universal Casio Forum** +and the **Casetta** project website (where some information about legacy +thingies have been regrouped). -Thanks to Simon Lothar, Teamfx and KermMartian for their help! -Thanks to the people on **Planète Casio** for their support! +Thanks to: +- Simon Lothar (mainly on Casiopeia) for its reverse engineering and + documentation (**fxReverse project documentation** with Andreas Bertheussen, + and `fx_calculators_SuperH_based.chm`); +- Teamfx for complementary information; +- KermMartian (from Cemetech) for its reverse engineering on Prizm-related + formats and test files; +- Florian Birée for its regrouped documentation (Casetta), like for tokens; +- Yves-Marie Morgan for opening Casemul's source code; +- Tom Wheeley for making CaS a free software; +- Him and Tom Lynn for documenting the legacy protocol (9700); +- Other people at **Planète Casio** for their support! diff --git a/include/libg1m.h b/include/libg1m.h index 8df10d7..f463ef1 100644 --- a/include/libg1m.h +++ b/include/libg1m.h @@ -90,7 +90,7 @@ int g1m_decode_mcsfile_head(g1m_mcshead_t *head, int raw_type, const unsigned char *groupname, const unsigned char *dirname, const unsigned char *filename, uint_fast32_t filesize); -int g1m_mcstype_correct(g1m_mcshead_t *head); +int g1m_correct_mcsfile_head(g1m_mcshead_t *head); /* open and decode MCS file */ int g1m_decode_mcsfile(g1m_mcsfile_t **handle, @@ -108,10 +108,10 @@ int g1m_decode_casfile(g1m_mcsfile_t **handle, int g1m_decode_casfile_data(g1m_mcsfile_t **handle, const g1m_mcshead_t *head, const unsigned char *data, size_t size); -/* open CAS protocol file head and content */ +/* open newer CAS protocol file head, make file, read content */ int g1m_decode_caspro_head(g1m_mcshead_t *head, g1m_buffer_t *buffer); -int g1m_decode_caspro_part(g1m_mcsfile_t **file, - const g1m_mcshead_t *head, g1m_buffer_t *buffer); +int g1m_make_caspro_file(g1m_mcsfile_t **file, const g1m_mcshead_t *head); +int g1m_decode_caspro_part(g1m_mcsfile_t **file, g1m_buffer_t *buffer); /* free handles */ void g1m_free(g1m_t *handle); diff --git a/include/libg1m/format.h b/include/libg1m/format.h index 07e45ba..d5f4735 100644 --- a/include/libg1m/format.h +++ b/include/libg1m/format.h @@ -27,15 +27,21 @@ /* ************************************************************************** */ /* The CASIOLINK (CAS) format */ /* ************************************************************************** */ -/* This is the basic file format that CASIO used until around 2004, when the - * fx-9860G (Graph 85) came out. It is linked with the legacy protocol, which - * cannot be implemented with a good management of this format. +/* This is the first file format used by the CASIO community; it was + * more or less a dump of the communications protocol CASIO used until + * the fx-9860G (Graph 85) was announced, around 2004. + * It was managed by the CaS software, made by Tom Wheeler with the help of + * other people like Tom Lynn. This software was developed around 1997. * - * All of the useful structures and constants are in the specific header. - * The function to get the libg1m MCS type out of the string types is in - * `libg1m/formatutils.h`. */ + * There were two main versions of this protocol, leading to two different + * versions of the CAS file specification: the original protocol, used on the + * CFX-9700G (called cas in libg1m), and the newer protocol, used on the + * CFX-9850 (called caspro in libg1m). + * + * Here are the two headers: */ # include +# include /* ************************************************************************** */ /* The FXI format */ /* ************************************************************************** */ diff --git a/include/libg1m/format/cas.h b/include/libg1m/format/cas.h index e1bca0d..8b3fb4a 100644 --- a/include/libg1m/format/cas.h +++ b/include/libg1m/format/cas.h @@ -1,5 +1,5 @@ /* ***************************************************************************** - * libg1m/format/cas.h -- the CAS file format description. + * libg1m/format/cas.h -- the older CAS file format description. * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey * * This file is part of libg1m. @@ -18,22 +18,26 @@ * ************************************************************************** */ #ifndef LIBG1M_FORMAT_CAS_H # define LIBG1M_FORMAT_CAS_H -# include # include # pragma pack(1) -/* The CASIOLINK format looks a lot like the legacy communication protocol, - * but the two are to distinguish. A CASIOLINK-encoded file is basically - * a set of one or more MCS files of the same type. +/* This is the first CASIOLINK format. It is more or less a raw dump of the + * communications protocol the 9700 uses. It is basically an MCS file. * - * The file has two parts, each starting with a 0x3A (':'). - * It starts with a header: */ + * A CASIOLINK-encoded file is made of one header and one or more parts. + * Each element is preceded by a 0x3A, and is a packet in the communications + * protocol interpretation. */ +/* ************************************************************************** */ +/* Header */ +/* ************************************************************************** */ +/* The header is the following: */ -struct casiolink_header { +struct cas_header { uint8_t data[2]; - uint8_t _specific[5]; /* type-specific subheader */ - uint8_t filename[12]; /* unused chars are filled with 0xFFs. */ - uint8_t _unused[19]; /* 0xFFs. */ + uint8_t misc[5]; /* type-specific subheader (miscallaneous data) */ + uint8_t filename[12]; /* editor filename. */ + uint8_t password[12]; /* editor password. */ + uint8_t _reserved[7]; /* 0xFFs */ uint8_t checksum; }; @@ -48,7 +52,7 @@ struct casiolink_header { # define casiolink_program_basen 0x40 /* base-n mode */ # define casiolink_program_drawst 0x80 /* draw stats graph */ -struct casiolink_spe_program { +struct cas_spe_program { uint8_t _unknown; uint16_t length; uint8_t flags; @@ -60,7 +64,7 @@ struct casiolink_spe_program { * * Now, here are the specific bytes for a screenshot: */ -struct casiolink_spe_screenshot { +struct cas_spe_screenshot { uint8_t height; uint8_t width; uint8_t _unused[3]; @@ -68,28 +72,10 @@ struct casiolink_spe_screenshot { /* The specific bytes for a number start with either "RA" or "CA", 'R' or 'C' * meaning the number is complex or not. */ - -/* This should be put somewhere else, as it represents the packets in - * a legacy protocol communication. (FIXME: maybe the new CAS header?) */ - -struct casiolink_new_header { - /* types */ - uint8_t type[4]; - uint8_t data[4]; - - /* data length */ - uint16_t length; - uint8_t name[8]; - - /* variable-related data */ - uint8_t prefix[8]; /* "Variable"? */ - uint8_t real; /* 'R' for real, 'C' for complex */ - uint8_t magic; /* 0x0A */ - - /* alignment */ - uint8_t _ffs[21]; - uint8_t checksum; -}; +/* ************************************************************************** */ +/* Content (parts) */ +/* ************************************************************************** */ +/* TODO */ # pragma pack() #endif /* LIBG1M_FORMAT_CAS_H */ diff --git a/include/libg1m/format/caspro.h b/include/libg1m/format/caspro.h new file mode 100644 index 0000000..b1674f3 --- /dev/null +++ b/include/libg1m/format/caspro.h @@ -0,0 +1,79 @@ +/* ***************************************************************************** + * libg1m/format/caspro.h -- the newer CAS file format description. + * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey + * + * This file is part of libg1m. + * libg1m is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3.0 of the License, + * or (at your option) any later version. + * + * libg1m is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libg1m; if not, see . + * ************************************************************************** */ +#ifndef LIBG1M_FORMAT_CASPRO_H +# define LIBG1M_FORMAT_CASPRO_H +# include +# pragma pack(1) + +/* This is the later CASIOLINK format. It is more or less a raw dump of the + * communications protocol the 9850 uses. It is basically an MCS file. + * + * A CASIOLINK-encoded file is made of one header and one or more parts. + * Each element is preceded by a 0x3A, and is a packet in the communications + * protocol interpretation. */ +/* ************************************************************************** */ +/* Header (first element) */ +/* ************************************************************************** */ +/* The header is the following: */ + +struct caspro_header { + /* types */ + uint8_t type[4]; + uint8_t data[3]; + + /* data length */ + uint8_t used; /* 0x00 if is reset/unused, 0x01 if used */ + uint16_t length; /* for a variable: same value as in `used` */ + uint8_t name[8]; + + /* variable-related data */ + uint8_t prefix[8]; /* "Variable" for vars, 0xFFs otherwise */ + uint8_t aux[8]; /* variable: "R\x0A"/"C\x0A", editor: password */ + + /* something else (?) */ + uint8_t nl[2]; /* 'NL' */ + uint8_t _ffs[11]; + + /* end of packet */ + uint8_t checksum; +}; + +/* ************************************************************************** */ +/* Variable/number */ +/* ************************************************************************** */ +/* Variable has the following structure (described in a comment): + * + * uint8_t magic[4]; + * Four bytes, always {0x00, 0x01, 0x00, 0x01} for a variable; + * cas_bcd_t real; + * The real part of the variable. + * + * If the real part has the complex flag enabled, then the following is there: + * + * cas_bcd_t imgn; + * The imaginary part of the variable. + * + * Then finally, everytime: + * + * uint8_t checksum; + * The checksum (calculated as for the header). */ + +/* TODO: other file formats */ +# pragma pack() +#endif /* LIBG1M_FORMAT_CASPRO_H */ diff --git a/include/libg1m/formatutils.h b/include/libg1m/formatutils.h index 21e1242..9b5ce9b 100644 --- a/include/libg1m/formatutils.h +++ b/include/libg1m/formatutils.h @@ -29,16 +29,20 @@ # include /* get type */ -int g1m_get_type_info(const char *path, +int g1m_maketype_std(const char *path, unsigned char *main_id, unsigned char *subtype, const char **info, int *check_one, int *check_two, - unsigned int *platform, unsigned int *type); + unsigned int *platform, g1m_type_t *type); /* get mcs type data */ -int g1m_mcstype_get(const char *groupname, const char *filename, - unsigned int rawtype, unsigned int *type, int *id); +int g1m_maketype_mcs(const char *groupname, const char *filename, + unsigned int rawtype, g1m_mcstype_t *type, int *id); /* get cas type data */ -int g1m_castype_get(const char *datatype, unsigned int *type); +int g1m_maketype_cas(const char *datatype, g1m_mcstype_t *type); + +/* get caspro type data */ +int g1m_maketype_caspro(const char *maintype, + const char *datatype, g1m_mcstype_t *type); #endif /* LIBG1M_FORMATUTILS_H */ diff --git a/include/libg1m/mcs.h b/include/libg1m/mcs.h index 71e13c7..c7c89a8 100644 --- a/include/libg1m/mcs.h +++ b/include/libg1m/mcs.h @@ -19,6 +19,7 @@ #ifndef LIBG1M_MCS_H # define LIBG1M_MCS_H # include +# include # define g1m_theta 27 # define g1m_r 28 # define g1m_ans 29 @@ -27,20 +28,25 @@ /* Main Memory Types */ /* ************************************************************************** */ /* MCS file type */ -typedef unsigned int g1m_mcsfile_type_t; -typedef unsigned int g1m_mcstype_t; -# define g1m_mcstype_unknown 0x0000 -# define g1m_mcstype_program 0x0001 -# define g1m_mcstype_list 0x0002 -# define g1m_mcstype_mat 0x0004 -# define g1m_mcstype_pict 0x0008 -# define g1m_mcstype_capt 0x0010 -# define g1m_mcstype_ssheet 0x0020 -# define g1m_mcstype_string 0x0040 -# define g1m_mcstype_setup 0x0080 -# define g1m_mcstype_alphamem 0x0100 -# define g1m_mcstype_vct 0x0200 -# define g1m_mcstype_variable 0x0400 +# define PRIXMCSTYPE "lX" +# define PRIxMCSTYPE "lx" +# define PRIuMCSTYPE "lu" +typedef long unsigned int g1m_mcsfile_type_t; +typedef g1m_mcsfile_type_t g1m_mcstype_t; + +# define g1m_mcstype_unknown 0x00000000 +# define g1m_mcstype_program 0x00000001 +# define g1m_mcstype_list 0x00000002 +# define g1m_mcstype_mat 0x00000004 +# define g1m_mcstype_pict 0x00000008 +# define g1m_mcstype_capt 0x00000010 +# define g1m_mcstype_ssheet 0x00000020 +# define g1m_mcstype_string 0x00000040 +# define g1m_mcstype_setup 0x00000080 +# define g1m_mcstype_alphamem 0x00000100 +# define g1m_mcstype_vct 0x00000200 +# define g1m_mcstype_variable 0x00000400 +# define g1m_mcstype_end 0x00000800 /* MCS file type aliases */ # define g1m_mcstype_matrix g1m_mcstype_mat @@ -71,6 +77,7 @@ typedef struct g1m_mcs_cell_s { /* Main structures */ /* ************************************************************************** */ /* mcs file head flags */ +# define g1m_mcsflag_last 0x8000 /* was the last part to be received */ # define g1m_mcsflag_complex 0x0001 /* is a complex variable */ /* mcs file head */ @@ -81,6 +88,8 @@ typedef struct g1m_mcshead_s { unsigned int flags; /* content size */ + int count; + unsigned int width, height; uint_fast32_t size; /* mcs-related raw data */ @@ -88,7 +97,11 @@ typedef struct g1m_mcshead_s { unsigned char _group[17], _dirname[9]; /* cas-related raw data */ - unsigned char _data[3]; + unsigned char _maintype[4]; + unsigned char _datatype[3]; + + /* the program password */ + char password[9]; } g1m_mcshead_t; /* mcs file */ @@ -101,19 +114,14 @@ typedef struct g1m_mcsfile_s { /* content (useful when not read) */ char *content; - /* for programs: the password */ - char password[9]; - /* for spreadsheets, lists and matrixes */ - unsigned int columns, rows; g1m_mcs_cell_t **cells; /* variables */ - int count; + g1m_mcs_cell_t var; g1m_mcs_cell_t *vars; /* for pictures and captures */ - unsigned int width, height; uint32_t **image; /* 0x0RGB */ uint32_t **second_image; /* 0x0RGB */ } g1m_mcsfile_t; diff --git a/src/core/free.c b/src/core/free.c index b6739eb..6743c3d 100644 --- a/src/core/free.c +++ b/src/core/free.c @@ -59,7 +59,7 @@ void g1m_free_mcsfile_content(g1m_mcsfile_t *handle) /* free cells */ if (type & (g1m_mcstype_mat | g1m_mcstype_vct | g1m_mcstype_list | g1m_mcstype_spreadsheet) - && handle->columns && handle->rows) { + && handle->head.width && handle->head.height) { free(handle->cells[0]); free(handle->cells); } diff --git a/src/decode/cas.c b/src/decode/cas.c index 011afba..7ea4395 100644 --- a/src/decode/cas.c +++ b/src/decode/cas.c @@ -42,7 +42,7 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, const char *datatype, if (!head) return (-1); /* check the data type */ - if (g1m_castype_get(datatype, &head->type)) + if (g1m_maketype_cas(datatype, &head->type)) return (g1m_error_unrecognized); /* fill the handle */ @@ -52,7 +52,7 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, const char *datatype, /* type specific */ if (head->type == g1m_mcstype_program) { - struct casiolink_spe_program *spe = (void*)specific; + struct cas_spe_program *spe = (void*)specific; head->size = be16toh(spe->length); /* TODO: store flags? */ } @@ -86,14 +86,14 @@ int g1m_decode_cas(g1m_t *handle, g1m_buffer_t *buffer, int err; /* read the header */ - DREAD(hd, casiolink_header) - if (g1m_checksum8(&hd, sizeof(struct casiolink_header) - 1) != hd.checksum) + DREAD(hd, cas_header) + if (g1m_checksum8(&hd, sizeof(struct cas_header) - 1) != hd.checksum) return (g1m_error_checksum); /* decrypt it */ g1m_mcshead_t head; if ((err = g1m_decode_casfile_head(&head, (char*)hd.data, - (char*)hd.filename, (char*)hd._specific))) + (char*)hd.filename, (char*)hd.misc))) return (err); /* TODO: decode it */ diff --git a/src/decode/casemul.c b/src/decode/casemul.c index 872269c..e8d6862 100644 --- a/src/decode/casemul.c +++ b/src/decode/casemul.c @@ -155,8 +155,8 @@ static int read_picture(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, /* set the pixels */ prepare_pixels(img, width, height) - file->width = width; - file->height = height; + file->head.width = width; + file->head.height = height; file->image = img; for (int x = 0; x < width; x++) for (int y = 0; y < height; y++) img[y][x] = colours[*px++]; @@ -215,8 +215,8 @@ static int read_matrix(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, /* TODO: id */ /* read the matrix */ - file->columns = width; - file->rows = height; + file->head.width = width; + file->head.height = height; for (int y = 0; y < height; y++) { /* correct offset in matrix */ file->cells[y] = &rws[width * y]; @@ -294,7 +294,8 @@ static int read_list(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, /* TODO: id */ /* read the list */ - file->columns = 1; file->rows = len; + file->head.width = 1; + file->head.height = len; for (int x = 0; x < len; x++) { /* correct matrix, read bcd */ file->cells[x] = &rws[x]; diff --git a/src/decode/caspro.c b/src/decode/caspro.c.draft similarity index 100% rename from src/decode/caspro.c rename to src/decode/caspro.c.draft diff --git a/src/decode/mcs/alphamem.c b/src/decode/mcs/alphamem.c index 8dd303b..ee68d36 100644 --- a/src/decode/mcs/alphamem.c +++ b/src/decode/mcs/alphamem.c @@ -35,16 +35,25 @@ int g1m_decode_mcs_alphamem(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, uint8_t buf[length]; READ(buf, length) - /* count number of vars */ - handle->count = length / (2 * sizeof(mcs_bcd_t)); + /* count number of vars, act if there is a single variable */ + int count = length / (2 * sizeof(mcs_bcd_t)); + handle->head.count = count; + if (count == 1) { + mcs_bcd_t *b = (void*)buf; + g1m_bcd_frommcs(b++, &handle->var.real); + g1m_bcd_frommcs(b++, &handle->var.imgn); + handle->var.used = 1; + handle->vars = &handle->var; /* compatibility */ + return (0); + } /* allocate the vars table */ - handle->vars = malloc(handle->count * sizeof(g1m_mcs_cell_t)); + handle->vars = malloc(handle->head.count * sizeof(g1m_mcs_cell_t)); if (!handle->vars) return (g1m_error_alloc); /* copy */ const mcs_bcd_t *b = (void*)buf; - for (int i = 0; i < handle->count; i++) { + for (int i = 0; i < count; i++) { g1m_bcd_frommcs(b++, &handle->vars[i].real); g1m_bcd_frommcs(b++, &handle->vars[i].imgn); handle->vars[i].used = 1; diff --git a/src/decode/mcs/list.c b/src/decode/mcs/list.c index 1861aba..b887c82 100644 --- a/src/decode/mcs/list.c +++ b/src/decode/mcs/list.c @@ -70,8 +70,8 @@ int g1m_decode_mcs_list(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, } /* fill final tab */ - handle->rows = elcount; - handle->columns = 1; + handle->head.height = elcount; + handle->head.width = 1; handle->cells = NULL; if (elcount) { #if LOGLEVEL >= ll_info diff --git a/src/decode/mcs/matrix.c b/src/decode/mcs/matrix.c index bb4a283..0c52b3b 100644 --- a/src/decode/mcs/matrix.c +++ b/src/decode/mcs/matrix.c @@ -46,8 +46,8 @@ int g1m_decode_mcs_matrix(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, log_info("Matrix size is %" PRIuFAST32 "*%" PRIuFAST32, w, h); /* store dimensions */ - handle->rows = w; - handle->columns = h; + handle->head.width = w; + handle->head.height = h; handle->cells = NULL; if (w && h) { diff --git a/src/decode/mcs/picture.c b/src/decode/mcs/picture.c index 43d8a66..2303b6c 100644 --- a/src/decode/mcs/picture.c +++ b/src/decode/mcs/picture.c @@ -95,14 +95,15 @@ int g1m_decode_mcs_capture(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, hd.height = be16toh(hd.height); /* store */ - handle->width = hd.width; - handle->height = hd.height; + handle->head.width = hd.width; + handle->head.height = hd.height; /* print info */ - log_info("capture is %dx%d sized", handle->width, handle->height); + log_info("capture is %dx%d sized", handle->head.width, handle->head.height); /* get the image and return */ - return (get_image(buffer, &handle->image, handle->width, handle->height)); + return (get_image(buffer, &handle->image, + handle->head.width, handle->head.height)); } /** @@ -121,8 +122,8 @@ int g1m_decode_mcs_picture(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, int err; /* store some dimensions, in case. */ - handle->width = 128; - handle->height = 64; + handle->head.width = 128; + handle->head.height = 64; /* get the first image */ if ((err = get_image(buffer, &handle->image, 128, 64))) { diff --git a/src/decode/mcs/program.c b/src/decode/mcs/program.c index 7af8505..1683a14 100644 --- a/src/decode/mcs/program.c +++ b/src/decode/mcs/program.c @@ -38,8 +38,8 @@ int g1m_decode_mcs_program(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, log_info("Program password is '%.8s'.", hd.password); /* store info */ - strncpy(handle->password, (char*)hd.password, 8); - handle->password[8] = 0; + strncpy(handle->head.password, (char*)hd.password, 8); + handle->head.password[8] = 0; /* get content */ size_t content_size = length - sizeof(struct mcs_programheader); diff --git a/src/decode/mcs/spreadsheet.c b/src/decode/mcs/spreadsheet.c index 167b340..1dfe063 100644 --- a/src/decode/mcs/spreadsheet.c +++ b/src/decode/mcs/spreadsheet.c @@ -109,11 +109,11 @@ int g1m_decode_mcs_spreadsheet(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, /* create final tab */ handle->cells = NULL; - handle->columns = 0; - handle->rows = 0; + handle->head.width = 0; + handle->head.height = 0; if (cells_count) { - handle->columns = cols; - handle->rows = rows; + handle->head.width = cols; + handle->head.height = rows; /* alloc */ g1m_mcs_cell_t **tab = malloc(sizeof(g1m_mcs_cell_t*) * cols); diff --git a/src/decode/std.c b/src/decode/std.c index 3388b1b..45a6a95 100644 --- a/src/decode/std.c +++ b/src/decode/std.c @@ -90,10 +90,11 @@ static int find_decode_function(g1m_t *handle, const char *path, struct standard_header *std, decode_func *rd) { /* get the type */ - unsigned int platform, type; + unsigned int platform; + g1m_type_t type; const char *type_string; int check_one, check_two; - if (g1m_get_type_info(path, std->main_id, std->subtype, &type_string, + if (g1m_maketype_std(path, std->main_id, std->subtype, &type_string, &check_one, &check_two, &platform, &type)) return (g1m_error_magic); log_info("Standard Header type is '%s'.", type_string); diff --git a/src/decode/std/mcs.c b/src/decode/std/mcs.c index 9659500..7d34e31 100644 --- a/src/decode/std/mcs.c +++ b/src/decode/std/mcs.c @@ -95,10 +95,10 @@ int g1m_decode_mcsfile_head(g1m_mcshead_t *head, if (!head) return (-1); /* look for the raw type */ - if (g1m_mcstype_get((char*)groupname, (char*)filename, raw_type, + if (g1m_maketype_mcs((char*)groupname, (char*)filename, raw_type, &head->type, &head->id)) head->type = g1m_mcstype_unknown; - log_info("libg1m file type is 0x%04X", head->type); + log_info("libg1m file type is 0x%08" PRIXMCSTYPE, head->type); #if LOGLEVEL <= ll_info if (g1m_mcstype_uses_id(head->type)) { log_info("libg1m file id is (%d, %d)", g1m_get_id_major(head->id), diff --git a/src/manage/mcs.c b/src/manage/mcs.c.draft similarity index 99% rename from src/manage/mcs.c rename to src/manage/mcs.c.draft index a44d0d1..9bcc899 100644 --- a/src/manage/mcs.c +++ b/src/manage/mcs.c.draft @@ -76,7 +76,7 @@ found:; file->head.id = id; /* and use mcstype utilities to copy other info */ - g1m_mcstype_correct(&file->head); + g1m_correct_mcsfile_head(&file->head); /* return it */ return (file); diff --git a/src/type/cas.c b/src/type/cas.c index b0988cc..f674944 100644 --- a/src/type/cas.c +++ b/src/type/cas.c @@ -27,7 +27,7 @@ struct type_corresp { const char *datatype; /* libg1m MCS file type */ - unsigned int type; + g1m_mcstype_t type; }; /* ************************************************************************** */ @@ -39,8 +39,6 @@ struct type_corresp { #define TTERM {NULL, 0} static struct type_corresp cas_groups[] = { - {"PG", g1m_mcstype_program}, - /* not implemented yet types, described by Tom Wheeley and Tom Lynn */ {"AA", 0}, // dynamic graph functions {"AD", 0}, // variable memory @@ -66,19 +64,6 @@ static struct type_corresp cas_groups[] = { {"SR", 0}, // linear regression data {"SS", 0}, // standard deviation data - /* not implemented yet types, described in libcafix */ - {"FT", 0}, // ??? - {"GM", 0}, // G-Mem? - {"LT", 0}, // List - {"MT", 0}, // Matrix - {"PC", 0}, // Picture - {"RF", 0}, // ??? - {"RR", 0}, // ??? - {"SE", 0}, // Equation? - {"TR", 0}, // ??? - {"VM", 0}, // Variable (A-Z, etc) - {"WD", 0}, // window data - /* terminating entry */ TTERM }; @@ -87,7 +72,7 @@ static struct type_corresp cas_groups[] = { /* Main functions */ /* ************************************************************************** */ /** - * g1m_castype_get: + * g1m_maketype_cas: * Get the libg1m MCS type from raw CAS identification data. * * @arg datatype the data type string. @@ -95,7 +80,7 @@ static struct type_corresp cas_groups[] = { * @return the error (if any). */ -int g1m_castype_get(const char *datatype, unsigned int *type) +int g1m_maketype_cas(const char *datatype, g1m_mcstype_t *type) { struct type_corresp *c = cas_groups - 1; while ((++c)->datatype) { diff --git a/src/type/caspro.c b/src/type/caspro.c new file mode 100644 index 0000000..43dceda --- /dev/null +++ b/src/type/caspro.c @@ -0,0 +1,82 @@ +/* ***************************************************************************** + * type/caspro.c -- get the newer CAS type out of raw identification data. + * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey + * + * This file is part of libg1m. + * libg1m is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3.0 of the License, + * or (at your option) any later version. + * + * libg1m is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libg1m; if not, see . + * ************************************************************************** */ +#include + +/* ************************************************************************** */ +/* Local types */ +/* ************************************************************************** */ +/* Correspondance type */ +struct type_corresp { + /* identification */ + const char *maintype; + const char *datatype; + + /* libg1m MCS file type */ + g1m_mcstype_t type; +}; + +/* ************************************************************************** */ +/* Correspondances */ +/* ************************************************************************** */ +/* All correspondances. Remarks: + * - 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", "MT", g1m_mcstype_variable}, + + /* terminating entry */ + TTERM +}; + +/* ************************************************************************** */ +/* Main functions */ +/* ************************************************************************** */ +/** + * g1m_maketype_caspro: + * Get the libg1m MCS type from raw CAS identification data. + * + * @arg datatype the data type string. + * @arg type[out] the libg1m MCS type. + * @return the error (if any). + */ + +int g1m_maketype_caspro(const char *maintype, + const char *datatype, g1m_mcstype_t *type) +{ + struct type_corresp *c; + for (c = cas_types; c->datatype; c++) { + if ((!c->maintype || !strncmp(maintype, c->maintype, 3)) /* 4? */ + && (!c->datatype || !strncmp(datatype, c->datatype, 2))) /* 4? */ + break; + } + if (!c->maintype) goto notfound; + + /* fill in info and return */ + if (type) *type = c->type; + return (0); + +notfound: + log_info("Type with '%.4s' data string was not implemented or not " + "recognized.", datatype); + if (type) *type = 0; + return (1); +} diff --git a/src/type/mcs.c b/src/type/mcs.c index 3a074db..be132fd 100644 --- a/src/type/mcs.c +++ b/src/type/mcs.c @@ -40,7 +40,7 @@ struct type_corresp { const char *info; /* libg1m information */ - unsigned int type; + g1m_mcstype_t type; }; /* Group correspondance type */ @@ -225,7 +225,7 @@ static int get_number(const char *s, int *num, int isnum) /** - * g1m_mcstype_get: + * g1m_maketype_mcs: * Get libg1m type from rawtype. * * @arg gname the MCS group name. @@ -236,8 +236,8 @@ static int get_number(const char *s, int *num, int isnum) * @return if the type was not found (0 if yes). */ -int g1m_mcstype_get(const char *gname, const char *fname, - unsigned int rawtype, unsigned int *type, int *id) +int g1m_maketype_mcs(const char *gname, const char *fname, + unsigned int rawtype, g1m_mcstype_t *type, int *id) { /* log what we're looking for */ log_info("Looking for type with '%.8s' group, '%.8s' name and " @@ -297,14 +297,14 @@ notfound: } /** - * g1m_mcstype_correct: + * g1m_correct_mcsfile_head: * Correct information. * * @arg head the mcs head to correct. * @return if an error was encountered. */ -int g1m_mcstype_correct(g1m_mcshead_t *head) +int g1m_correct_mcsfile_head(g1m_mcshead_t *head) { /* check if there is a type */ if (!head || !head->type) diff --git a/src/type/main.c b/src/type/std.c similarity index 97% rename from src/type/main.c rename to src/type/std.c index 04c2b35..2f7520e 100644 --- a/src/type/main.c +++ b/src/type/std.c @@ -1,5 +1,5 @@ /* ***************************************************************************** - * type/main.c -- extract the G1M file type out of raw identification data. + * type/std.c -- extract the STD file type out of raw identification data. * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey * * This file is part of libg1m. @@ -173,7 +173,7 @@ static void get_extension(const char *path, char *extbuf) /* Main functions */ /* ************************************************************************** */ /** - * g1m_get_type_info: + * g1m_maketype_std: * Get type info. * * @arg path Path of the file. @@ -187,10 +187,10 @@ static void get_extension(const char *path, char *extbuf) * @return If there was an error. */ -int g1m_get_type_info(const char *path, +int g1m_maketype_std(const char *path, unsigned char *main_id, unsigned char *subtype, const char **info, int *check_one, int *check_two, - unsigned int *platform, unsigned int *type) + unsigned int *platform, g1m_type_t *type) { /* look if blank */ if (!memcmp(main_id, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8)