diff --git a/include/libg1m.h b/include/libg1m.h index bd9e1ee..8df10d7 100644 --- a/include/libg1m.h +++ b/include/libg1m.h @@ -108,6 +108,11 @@ 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 */ +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); + /* free handles */ void g1m_free(g1m_t *handle); void g1m_free_mcsfile(g1m_mcsfile_t *handle); diff --git a/src/core/decode.c b/src/core/decode.c index f67f182..7e99f04 100644 --- a/src/core/decode.c +++ b/src/core/decode.c @@ -47,11 +47,12 @@ int g1m_decode(g1m_t *handle, const char *path, g1m_buffer_t *buffer, READ(&buf[1], 3) if (!memcmp(buf, "CAFS", 4)) { handle->platform |= g1m_platflag_be; + return (g1m_decode_casemul(handle, buffer)); } else if (!memcmp(buf, "ACFS", 4)) return (g1m_decode_casemul(handle, buffer)); /* identify a standard header (send a _copy_) */ - READ(&buf[1], 0x1C) + READ(&buf[4], 0x1C) uint8_t altbuf[0x20]; memcpy(altbuf, buf, 0x20); return (g1m_decode_std(handle, path, buffer, (struct standard_header*)altbuf, expected_types)); diff --git a/src/decode/casemul.c b/src/decode/casemul.c index 100dfd6..872269c 100644 --- a/src/decode/casemul.c +++ b/src/decode/casemul.c @@ -57,7 +57,6 @@ static int read_internal(g1m_buffer_t *buffer, uint32_t signature, /* check version */ if (le32toh(hd.version) != version) { - log_error("version mismatch!"); log_error("version mismatch!"); log_error("epxected %08" PRIxFAST32 ", got %08" PRIx32, version, hd.version); @@ -90,7 +89,6 @@ static int read_top(g1m_buffer_t *buffer, char *name, uint_fast32_t *length) name_length = max(name_length, 8); memcpy(name, buf, name_length); name[name_length] = 0; - logm_info(name, name_length); /* read the length and correct */ READ(length, sizeof(uint32_t)) @@ -133,6 +131,7 @@ static int read_picture(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, /* specific things */ DREAD(pct, casemul_pict_header) + log_info("picture dimension is %d*%dpx", pct.width, pct.height); /* read all of the pixels */ unsigned int total = pct.width * pct.height; @@ -190,10 +189,11 @@ static int read_matrix(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, /* read specific things */ DREAD(mtx, casemul_mtrx_header) - - /* read double tab */ int width = le32toh(mtx.lines) & 0x7FFF, height = le32toh(mtx.columns) & 0x7FFF; + log_info("%d*%d elements in matrix", width, height); + + /* read double tab */ unsigned int total = width * height; double tab[total]; READ(tab, total * sizeof(double)) double *raw = tab; @@ -218,9 +218,22 @@ static int read_matrix(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, file->columns = width; file->rows = height; for (int y = 0; y < height; y++) { + /* correct offset in matrix */ file->cells[y] = &rws[width * y]; + + /* read column */ for (int x = 0; x < width; x++) { + /* read the bcd */ g1m_bcd_t bcd; g1m_bcd_fromdouble(*raw++, &bcd); + +#if LOGLEVEL <= ll_info + /* log the bcd */ + char buf[G1M_BCD_GOODBUFSIZE]; + g1m_bcdtoa(&bcd, buf, G1M_BCD_GOODBUFSIZE); + log_info("[%d][%d] %s", y, x, buf); +#endif + + /* make the cell */ file->cells[y][x] = (g1m_mcs_cell_t){ .real = bcd, .imgn = {}, @@ -257,9 +270,10 @@ static int read_list(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, /* read specific things */ DREAD(lst, casemul_list_header) + int len = le32toh(lst.lines) & 0x7FFF; + log_info("%d elements in list", len); /* read double tab */ - int len = le32toh(lst.lines) & 0x7FFF; double tab[len]; READ(tab, len * sizeof(double)) double *raw = tab; @@ -282,8 +296,18 @@ static int read_list(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, /* read the list */ file->columns = 1; file->rows = len; for (int x = 0; x < len; x++) { + /* correct matrix, read bcd */ file->cells[x] = &rws[x]; g1m_bcd_t bcd; g1m_bcd_fromdouble(*raw++, &bcd); + +#if LOGLEVEL <= ll_info + /* log information */ + char buf[G1M_BCD_GOODBUFSIZE]; + g1m_bcdtoa(&bcd, buf, G1M_BCD_GOODBUFSIZE); + log_info("[%d] %s", x, buf); +#endif + + /* set the cell */ file->cells[x][0] = (g1m_mcs_cell_t){ .real = bcd, .imgn = {}, @@ -321,13 +345,20 @@ int g1m_decode_casemul(g1m_t *handle, g1m_buffer_t *buffer) /* read the overall (global) header */ DREAD(glb, casemul_header) +#if LOGLEVEL <= ll_info + glb.source_offset = e32toh(glb.source_offset); + glb.compiled_offset = e32toh(glb.compiled_offset); + log_info("Header source offset is: 0x%08X", glb.source_offset); + if (glb.flags & casemul_compiled) + log_info("Header compiled offset is: 0x%08X", glb.compiled_offset); + else + log_info("The file has got no compiled part."); +#endif /* read the source header */ if ((err = read_internal(buffer, MAKELONG('SR', 'CE'), VER))) return (err); DREAD(src, casemul_source_header) - log_info("%d program(s), %d pic(s), %d matrix(es), %d list(s)", - src.programs, src.pictures, src.matrixes, src.lists); /* prepare the tab */ handle->type = g1m_type_mcs; @@ -341,6 +372,8 @@ int g1m_decode_casemul(g1m_t *handle, g1m_buffer_t *buffer) /* read each program; TODO: put this in a function when token parsing * is managed. */ for (int i = 0; i < src.programs; i++) { + log_info("Reading program #%d", i + 1); + log_warn("Program content will be skipped!"); /* general record things */ char name[13]; uint_fast32_t record_length; if ((err = read_top(buffer, name, &record_length)) @@ -357,6 +390,7 @@ int g1m_decode_casemul(g1m_t *handle, g1m_buffer_t *buffer) /* read each picture */ for (int i = 0; i < src.pictures; i++) { + log_info("Reading picture #%d", i + 1); if ((err = read_picture(&handle->files[handle->count], buffer, big_endian))) goto fail; @@ -365,6 +399,7 @@ int g1m_decode_casemul(g1m_t *handle, g1m_buffer_t *buffer) /* read each matrix */ for (int i = 0; i < src.matrixes; i++) { + log_info("Reading matrix #%d", i + 1); if ((err = read_matrix(&handle->files[handle->count], buffer, big_endian))) goto fail; @@ -373,6 +408,7 @@ int g1m_decode_casemul(g1m_t *handle, g1m_buffer_t *buffer) /* read each list */ for (int i = 0; i < src.lists; i++) { + log_info("Reading list #%d", i + 1); if ((err = read_list(&handle->files[handle->count], buffer, big_endian))) goto fail; @@ -380,6 +416,7 @@ int g1m_decode_casemul(g1m_t *handle, g1m_buffer_t *buffer) } /* TODO: skip compiled part? */ + log_warn("Should read compiled part here!"); /* no error! */ return (0); diff --git a/src/decode/caspro.c b/src/decode/caspro.c new file mode 100644 index 0000000..61dbde2 --- /dev/null +++ b/src/decode/caspro.c @@ -0,0 +1,55 @@ +/* ***************************************************************************** + * 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 + +/** + * 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) +{ + /* TODO */ + return (g1m_error_unknown); +} + +/** + * 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 buffer the buffer to read from. + * @return if there was an error, or not. + */ + +int g1m_decode_caspro_part(g1m_mcsfile_t **file, + const g1m_mcshead_t *head, g1m_buffer_t *buffer) +{ + /* TODO */ + return (g1m_error_unknown); +} diff --git a/src/decode/std/eact.c b/src/decode/std/eact.c index 03d4ed6..b756fbe 100644 --- a/src/decode/std/eact.c +++ b/src/decode/std/eact.c @@ -47,10 +47,7 @@ static int eact_decode_content_eact(g1m_line_t *handle, uint8_t *buf, handle->lines = NULL; /* check if the buffer is non-empty */ - if (!bufsize) { - log_info("Content was name-only."); - return (0); - } + if (!bufsize) return (0); /* get e-act subheader */ if (bufsize < sizeof(struct eact_eactheader)) return (g1m_error_eof); @@ -187,18 +184,20 @@ static int eact_decode_line_content(g1m_line_t *handle, uint8_t *buf, break ; ctype++; } - if (!ctype->decode) { - log_error("Unknown content type: '%.8s'", hd.type); - return (0); + + /* print the content */ +#if LOGLEVEL <= ll_info + if (!ctype->decode) log_error("Type is unmanaged!"); + + if (!size) log_info("Content was name-only."); + else if (!ctype->decode) { + log_info("Content was:"); + logm_info(buf, size); } +#endif /* then decode */ - int err; - if ((err = (*ctype->decode)(handle, buf, size))) - return (err); - - /* otherwise, no error. */ - return (0); + return (ctype->decode ? (*ctype->decode)(handle, buf, size) : 0); } /**