From 2ef6ceb4978bb642311f6ef8340d187b85c55d4f Mon Sep 17 00:00:00 2001 From: "Thomas \"Cakeisalie5\" Touhey" Date: Tue, 7 Mar 2017 14:26:00 +0100 Subject: [PATCH] Can now decode CAS files! --- .gitmodules | 0 AUTHORS.md | 2 +- include/libg1m.h | 22 ++-- include/libg1m/format.h | 20 +-- include/libg1m/format/caspro.h | 2 +- include/libg1m/internals.h | 7 +- include/libg1m/mcs.h | 1 + src/core/strerror.c | 2 + src/decode/cas.c | 227 +++++++++++++++++++++++++++++---- src/decode/caspro.c | 133 ------------------- src/decode/mcs/program.c | 27 ++++ src/decode/mcs/var.c | 8 +- src/type/cas.c | 1 + src/type/caspro.c | 6 +- src/type/mcs.c | 5 +- 15 files changed, 267 insertions(+), 196 deletions(-) delete mode 100644 .gitmodules delete mode 100644 src/decode/caspro.c diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29..0000000 diff --git a/AUTHORS.md b/AUTHORS.md index 0195d6a..62b6521 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -1,5 +1,5 @@ # libg1m authors -Copyright (C) 2017 Thomas "Cakeisalie5" Touhey +Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <> The documentation comes from a lot of places in the CASIO community, but mainly from **Casiopeia**, **Cemetech** (Prizm-related), the **Universal Casio Forum** diff --git a/include/libg1m.h b/include/libg1m.h index 77b5ec0..f517b29 100644 --- a/include/libg1m.h +++ b/include/libg1m.h @@ -101,20 +101,14 @@ int g1m_decode_mcsfile(g1m_mcsfile_t **handle, 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 (TODO: correct it for encoding) */ -int g1m_decode_casfile_head(g1m_mcshead_t *head, - const char *datatype, const char *filename, const char *specific); - -/* open and decode CAS file */ -int g1m_decode_casfile(g1m_mcsfile_t **handle, - const g1m_mcshead_t *head, g1m_buffer_t *buffer); -int g1m_decode_casfile_data(g1m_mcsfile_t **handle, - const g1m_mcshead_t *head, const unsigned char *data, size_t size); - -/* 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_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); +/* open CAS head for decoding + * -------------------------- + * if the head corresponds to something you want as a file (e.g. 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) */ +int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer); +int g1m_decode_casfile_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 d5f4735..edbcb09 100644 --- a/include/libg1m/format.h +++ b/include/libg1m/format.h @@ -33,12 +33,12 @@ * 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. * - * 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). + * There is only one protocol, but with two different versions of the headers, + * leading to different CAS file specifications: there is the original header + * format, used on the CFX-9700G (called cas in libg1m), and the newer protocol, + * used on the CFX-9850G (called caspro in libg1m). * - * Here are the two headers: */ + * Here are the two headers formats: */ # include # include @@ -66,12 +66,14 @@ * but save its files in its own format, which use the .cas extension * (like the CASIOLINK format, but the two formats are completely different). * - * It starts with a four-letter magic string, "ACFS". In fact, it is - * "CASF", like in "CasFile", the name of the real header. */ + * It starts with a four-letter magic string, either "CASF" (CasFile) if the + * file was written on a big endian platform, or "ACFS" if the platform was + * little-endian. */ -# define CASEMUL_MAGIC "ACFS" +# define CASEMUL_MAGIC_BE "CASF" +# define CASEMUL_MAGIC_LE "ACFS" -/* Discover the rest in its own header: */ +/* Discover the rest in its dedicated header: */ # include /* ************************************************************************** */ diff --git a/include/libg1m/format/caspro.h b/include/libg1m/format/caspro.h index 1bf13fd..e2e06d6 100644 --- a/include/libg1m/format/caspro.h +++ b/include/libg1m/format/caspro.h @@ -48,7 +48,7 @@ struct caspro_header { /* something else (?) */ uint8_t nl[2]; /* 'NL'? */ - uint8_t _reserved[11]; + uint8_t _reserved[12]; /* end of packet */ uint8_t checksum; diff --git a/include/libg1m/internals.h b/include/libg1m/internals.h index e5ee168..2f54abd 100644 --- a/include/libg1m/internals.h +++ b/include/libg1m/internals.h @@ -137,10 +137,11 @@ G1M_MCSFUNC(string) /* ************************************************************************** */ /* CASPRO-specific decoding functions */ /* ************************************************************************** */ -# define G1M_CASPROFUNC(NAME) \ -int g1m_decode_caspro_##NAME(g1m_mcsfile_t *handle, g1m_buffer_t *buffer); +# define G1M_CASFUNC(NAME) \ +int g1m_decode_caspart_##NAME(g1m_mcsfile_t *handle, g1m_buffer_t *buffer); -G1M_CASPROFUNC(var) +G1M_CASFUNC(var) +G1M_CASFUNC(program) /* ************************************************************************** */ /* Picture utilities */ /* ************************************************************************** */ diff --git a/include/libg1m/mcs.h b/include/libg1m/mcs.h index ed6a173..c21bd49 100644 --- a/include/libg1m/mcs.h +++ b/include/libg1m/mcs.h @@ -85,6 +85,7 @@ typedef struct g1m_mcs_cell_s { /* mcs file type -- what type of raw information is there * e.g. `head.flags & g1m_mcsmask_info == g1m_mcsinfo_g1m` */ +# define g1m_mcsinfo(H) ((H)->flags & g1m_mcsmask_info) # define g1m_mcsmask_info 0x6000 # define g1m_mcsinfo_none 0x0000 # define g1m_mcsinfo_mcs 0x2000 diff --git a/src/core/strerror.c b/src/core/strerror.c index 8cecb1c..fb21479 100644 --- a/src/core/strerror.c +++ b/src/core/strerror.c @@ -41,6 +41,8 @@ const char *g1m_error_strings[] = { [g1m_error_wrong_type] = "was not of the expected type", + [g1m_error_checksum] = + "a checksum problem occured", [g1m_error_magic] = "is probably not a file libg1m can parse, or is corrupted", [g1m_error_eof] = diff --git a/src/decode/cas.c b/src/decode/cas.c index 96412a2..5fd579b 100644 --- a/src/decode/cas.c +++ b/src/decode/cas.c @@ -20,39 +20,135 @@ * https://casetta.tuxfamily.org/formats/cas * ************************************************************************** */ #include +#define FUNC(NAME) g1m_decode_caspart_##NAME /* ************************************************************************** */ -/* Head decoding function */ +/* Type correspondance list */ /* ************************************************************************** */ +/* Part parsing function type */ +typedef int (*cas_decode_function)(g1m_mcsfile_t*, g1m_buffer_t*); + +/* Correspondance type */ +struct cas_corresp { + unsigned int type; + cas_decode_function decode; +}; + +/* All correspondances */ +#define TTERM {0, NULL} +static struct cas_corresp cas_types[] = { + {g1m_mcstype_var, FUNC(var)}, + {g1m_mcstype_program, FUNC(program)}, + TTERM +}; + +/** + * lookup_cas_decode: + * Lookup for a parsing function for the CAS part. + * + * @arg type the libg1m MCS file type. + * @return the function (NULL if not found). + */ + +static cas_decode_function lookup_cas_decode(g1m_mcstype_t type) +{ + /* lookup for the type */ + struct cas_corresp *c = cas_types; + while (c->decode) { + if (type == c->type) + break; + c++; + } + + /* return the function */ + return (c->decode); +} + +/* ************************************************************************** */ +/* Head decoding functions */ +/* ************************************************************************** */ +/** + * decode_caspro_head: + * Decode a CASIOLINK Protocol header. + * + * @arg head the head to fill. + * @arg hd the header. + * @return if there was an error, or not. + */ + +static int decode_caspro_head(g1m_mcshead_t *head, struct caspro_header *hd) +{ + /* log the raw header */ + log_info("Raw CASPRO header:"); + logm_info(hd, sizeof(struct caspro_header)); + + /* check the checksum */ + uint8_t csum = ~g1m_checksum8(hd, sizeof(struct caspro_header) - 1) + 1; + if (csum != hd->checksum) + return (g1m_error_checksum); + + /* copy the basic information */ + head->size = be16toh(hd->length) - 2 /* checksum, colon */; + char *end = memchr(hd->name, 0xFF, 8); + size_t len = end ? (size_t)(end - (char*)hd->name) : 8; + memcpy(head->name, hd->name, len); head->name[len] = 0; + + /* read specific data */ + switch (head->type) { + case g1m_mcstype_program:; + /* copy password */ + head->flags |= g1m_mcsflag_unfinished; + end = memchr(hd->aux, 0xFF, 8); + len = end ? (size_t)(end - (char*)hd->aux) : 8; + memcpy(head->password, hd->aux, len); head->password[len] = 0; + break; + case g1m_mcstype_variable: + if (hd->used) head->flags |= g1m_mcsflag_unfinished; + /* TODO: id */ + head->count = 1; + break; + } + + /* TODO */ + return (0); +} + /** * g1m_decode_casfile_head: * Decode the CAS file head. * * @arg head the head to decode. - * @arg datatype the raw data type (at least 2 bytes). - * @arg filename the file name (at least 12 bytes). - * @arg specific the specific bytes (at least 5 bytes). + * @arg buffer the buffer to read the header from. * @return the error code (0 if ok). */ -int g1m_decode_casfile_head(g1m_mcshead_t *head, const char *datatype, - const char *filename, const char *specific) +int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer) { /* check that the head exists */ if (!head) return (-1); + /* read beginning of the header, try to guess a newer header */ + uint8_t buf[49]; READ(buf, 7) + struct caspro_header *phd = (void*)buf; + if (!g1m_maketype_caspro(head, (char*)phd->type, (char*)phd->data)) { + READ(&buf[7], 42) + return (decode_caspro_head(head, phd)); + } + /* check the data type */ - if (g1m_maketype_cas(head, datatype)) + READ(&buf[7], 32) + struct cas_header *hd = (void*)buf; + log_info("Raw CAS header:"); + logm_info(hd, sizeof(struct cas_header)); + if (g1m_maketype_cas(head, (char*)hd->data)) return (g1m_error_unrecognized); /* fill the handle */ - memset(head->_dirname, 0, 9); - memset(head->_group, 0, 17); - memcpy(head->name, filename, 12); head->name[12] = 0; + memcpy(head->name, hd->filename, 12); head->name[12] = 0; /* type specific */ if (head->type == g1m_mcstype_program) { - struct cas_spe_program *spe = (void*)specific; + struct cas_spe_program *spe = (void*)hd->misc; head->size = be16toh(spe->length); /* TODO: store flags? */ } @@ -62,10 +158,32 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, const char *datatype, } /* ************************************************************************** */ -/* File decoding functions */ +/* Part decoding functions */ /* ************************************************************************** */ -/* TODO: g1m_decode_casfile */ -/* TODO: g1m_decode_casfile_data */ +/** + * g1m_decode_casfile_part: + * Decode a CASIOLINK Protocol content part. + * + * @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_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer) +{ + /* checks */ + if (!file) return (g1m_error_op); + + /* look for the decoding function */ + cas_decode_function decode = lookup_cas_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)); +} /* ************************************************************************** */ /* File decoding function */ @@ -74,6 +192,8 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, const char *datatype, * g1m_decode_cas: * Decode a CAS file. TODO. * + * The colon ':' (0x3A) is already read at this point. + * * @arg handle the handle to create. * @arg buffer the buffer to read from. * @arg expected_types the expected types. @@ -85,18 +205,73 @@ int g1m_decode_cas(g1m_t *handle, g1m_buffer_t *buffer, { int err; - /* read the header */ - DREAD(hd, cas_header) - if (g1m_checksum8(&hd, sizeof(struct cas_header) - 1) != hd.checksum) - return (g1m_error_checksum); + /* prepare the handle */ + handle->type = g1m_type_mcs; + handle->files = NULL; + handle->_size = 0; - /* decrypt it */ - g1m_mcshead_t head; - if ((err = g1m_decode_casfile_head(&head, (char*)hd.data, - (char*)hd.filename, (char*)hd.misc))) - return (err); + /* read each */ + for (handle->count = 0;;) { + /* read the head */ + log_info("Reading file head #%d", handle->count); + g1m_mcshead_t head; + if ((err = g1m_decode_casfile_head(&head, buffer))) goto fail; + if (head.type == g1m_mcstype_end) break; - /* TODO: decode it */ - /* everything went fine :) */ - return (g1m_error_wrong_type); + /* prepare space in the index */ + if (handle->count == handle->_size) { + int newsize = handle->_size + 4; + log_info("index not big enough, allocating from %d to %d slots", + handle->_size, newsize); + + /* allocate new index */ + err = g1m_error_alloc; + g1m_mcsfile_t **index = calloc(sizeof(g1m_mcsfile_t*), newsize); + if (!index) goto fail; + + /* copy old data */ + memcpy(index, handle->files, + sizeof(g1m_mcsfile_t*) * handle->_size); + memset(&index[handle->_size], 0, + sizeof(g1m_mcsfile_t*) * (newsize - handle->_size)); + handle->files = index; + handle->_size = newsize; + } + + /* prepare the file */ + log_info("Preparing the file."); + err = g1m_make_mcsfile(&handle->files[handle->count], &head); + if (err) goto fail; + + /* read each part */ + g1m_mcsfile_t *file = handle->files[handle->count]; handle->count++; +#if LOGLEVEL <= ll_info + for (int j = 1; file->head.flags & g1m_mcsflag_unfinished; j++) { +#else + while (file->head.flags & g1m_mcsflag_unfinished) { +#endif + log_info("Reading part #%d", j); + /* read the colon */ + uint8_t colon; GREAD(&colon, 1) + err = g1m_error_magic; + if (colon != ':') goto fail; + + /* read the part */ + err = g1m_decode_casfile_part(file, buffer); + if (err) goto fail; + } + + /* read first colon of the next part */ + err = g1m_error_magic; + uint8_t nextcolon; GREAD(&nextcolon, 1) + if (nextcolon != ':') goto fail; + } + + /* everything went well :) */ + return (0); + +fail: + /* END OF DA WORLD */ + g1m_free_mcs(handle); + return (err); } diff --git a/src/decode/caspro.c b/src/decode/caspro.c deleted file mode 100644 index 135acf2..0000000 --- a/src/decode/caspro.c +++ /dev/null @@ -1,133 +0,0 @@ -/* ***************************************************************************** - * decode/caspro.c -- decode legacy CASIO protocol 'file'. - * 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 . - * - * Based on the Casetta project documentation: - * 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 */ -/* ************************************************************************** */ -/** - * g1m_decode_caspro_head: - * Decode a CASIOLINK Protocol header. - * - * @arg head the head to fill. - * @arg buffer the buffer to read from. - * @return if there was an error, or not. - */ - -int g1m_decode_caspro_head(g1m_mcshead_t *head, g1m_buffer_t *buffer) -{ - /* read header, get type */ - DREAD(hd, caspro_header) - hd.length = be16toh(hd.length); - if (g1m_maketype_caspro(head, (char*)hd.type, (char*)hd.data)) - return (g1m_error_unknown); - - /* read specific data */ - 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 */ - return (0); -} - -/* ************************************************************************** */ -/* Part decoding function */ -/* ************************************************************************** */ -/** - * g1m_decode_caspro_part: - * Decode a CASIOLINK Protocol content part. - * - * @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) -{ - /* 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/program.c b/src/decode/mcs/program.c index 7179e4b..53d903a 100644 --- a/src/decode/mcs/program.c +++ b/src/decode/mcs/program.c @@ -58,3 +58,30 @@ fail: *handle = NULL; return (err); } + +/** + * g1m_decode_caspart_program: + * Decode a CAS program 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_program(g1m_mcsfile_t *handle, g1m_buffer_t *buffer) +{ + /* get content */ + READ(handle->content, handle->head.size) + log_info("Program content is:"); + logm_info(handle->content, handle->head.size); + + /* check the sum */ + uint8_t checksum; READ(&checksum, 1) + uint8_t csum = ~g1m_checksum8(handle->content, handle->head.size) + 1; + if (csum != checksum) + return (g1m_error_checksum); + + /* everything went well :) */ + handle->head.flags &= ~g1m_mcsflag_unfinished; + return (0); +} diff --git a/src/decode/mcs/var.c b/src/decode/mcs/var.c index 22d5726..94a74cf 100644 --- a/src/decode/mcs/var.c +++ b/src/decode/mcs/var.c @@ -55,15 +55,15 @@ int g1m_decode_mcs_var(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, } /** - * g1m_decode_caspro_var: - * Decode variable. + * g1m_decode_caspart_var: + * Decode a CAS variable 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_caspro_var(g1m_mcsfile_t *handle, g1m_buffer_t *buffer) +int g1m_decode_caspart_var(g1m_mcsfile_t *handle, g1m_buffer_t *buffer) { /* read the magic and real part */ uint8_t magic[4]; READ(magic, 4) @@ -81,7 +81,7 @@ int g1m_decode_caspro_var(g1m_mcsfile_t *handle, g1m_buffer_t *buffer) /* check the checksum */ uint8_t checksum; READ(&checksum, 1) - if (csum != checksum) + if (~csum + 1 != checksum) return (g1m_error_checksum); if (memcmp(magic, "\0\1\0\1", 4)) return (g1m_error_magic); diff --git a/src/type/cas.c b/src/type/cas.c index ad927d6..b9993a3 100644 --- a/src/type/cas.c +++ b/src/type/cas.c @@ -83,6 +83,7 @@ static struct type_corresp cas_groups[] = { int g1m_maketype_cas(g1m_mcshead_t *head, const char *datatype) { /* copy information */ + memset(head, 0, sizeof(g1m_mcshead_t)); head->flags |= g1m_mcsinfo_cas; memcpy(head->_datatype, datatype, 2); head->_datatype[2] = 0; diff --git a/src/type/caspro.c b/src/type/caspro.c index 426441d..f8c3f9f 100644 --- a/src/type/caspro.c +++ b/src/type/caspro.c @@ -42,6 +42,7 @@ struct type_corresp { 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}, /* terminating entry */ @@ -65,6 +66,7 @@ int g1m_maketype_caspro(g1m_mcshead_t *head, const char *maintype, 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; @@ -74,8 +76,8 @@ int g1m_maketype_caspro(g1m_mcshead_t *head, /* look for correspondance */ struct type_corresp *c; for (c = cas_types; c->datatype; c++) { - if ((!c->maintype || !strncmp(maintype, c->maintype, 3)) - && (!c->datatype || !strncmp(datatype, c->datatype, 2))) + if ((!c->maintype || !strncmp(maintype, c->maintype, 4)) + && (!c->datatype || !strncmp(datatype, c->datatype, 3))) break; } if (!c->maintype) goto notfound; diff --git a/src/type/mcs.c b/src/type/mcs.c index e796f29..7bf4105 100644 --- a/src/type/mcs.c +++ b/src/type/mcs.c @@ -62,8 +62,6 @@ struct group_corresp { * or lists, but they abandoned that. Why they made such groups, I have no * idea yet. * - 0xfe is more or less the generic type ID for "data". - * - I skipped the 'LISTFILE %d' groups are they are more or less duplicates - * of normal lists. * - Types with a directory name starting with '@' are app-specific files, with * the dirname being the internal name of the related application. */ @@ -79,7 +77,7 @@ static struct group_corresp mcs_groups[] = { {0x00, "ALPHA MEM", 0, "$GLOBAL", "alpha memory", g1m_mcstype_alphamem}, {0x00, "", arg | arg_is_let, "$GLOBAL", - "alpha memory", g1m_mcstype_variable}, + "variable", g1m_mcstype_variable}, TTERM }}, {"STRING ", arg | arg_is_num, (struct type_corresp[]){ @@ -245,6 +243,7 @@ int g1m_maketype_mcs(g1m_mcshead_t *head, "0x%02X raw type", gname, fname, rawtype); /* copy raw information */ + memset(head, 0, sizeof(g1m_mcshead_t)); head->flags |= g1m_mcsinfo_mcs; memcpy(head->name, fname, 8); head->name[8] = 0;