From 6f52a704de9a513557016bdc6d99866feedca411 Mon Sep 17 00:00:00 2001 From: "Thomas \"Cakeisalie5\" Touhey" Date: Mon, 6 Mar 2017 12:10:35 +0100 Subject: [PATCH] Simplified way MCS files are allocated. --- include/libg1m.h | 5 +- include/libg1m/buffer.h | 41 +++++ include/libg1m/format/caspro.h | 4 +- include/libg1m/formatutils.h | 19 ++- include/libg1m/internals.h | 47 +----- include/libg1m/mcs.h | 39 +++-- src/core/free.c | 12 +- src/decode/cas.c | 2 +- src/decode/casemul.c | 124 ++++++--------- src/decode/{caspro.c.draft => caspro.c} | 26 +++- src/decode/mcs/list.c | 114 ++++++-------- src/decode/mcs/matrix.c | 103 ++++++------ src/decode/mcs/picture.c | 69 ++++---- src/decode/mcs/program.c | 37 +++-- src/decode/mcs/setup.c | 12 +- src/decode/mcs/spreadsheet.c | 46 ++---- src/decode/mcs/string.c | 18 ++- src/decode/mcs/{alphamem.c => var.c} | 45 ++---- src/decode/std/mcs.c | 70 +++------ src/decode/std/picture.c | 2 +- src/manage/{mcs.c.draft => mcs.c} | 199 ++++++++++++++++-------- src/type/cas.c | 14 +- src/type/caspro.c | 23 ++- src/type/mcs.c | 34 ++-- src/utils/skip.c | 1 + 25 files changed, 564 insertions(+), 542 deletions(-) rename src/decode/{caspro.c.draft => caspro.c} (62%) rename src/decode/mcs/{alphamem.c => var.c} (54%) rename src/manage/{mcs.c.draft => mcs.c} (55%) diff --git a/include/libg1m.h b/include/libg1m.h index f463ef1..77b5ec0 100644 --- a/include/libg1m.h +++ b/include/libg1m.h @@ -85,6 +85,9 @@ int g1m_fopen(g1m_t **handle, const char *path, FILE *stream, g1m_type_t expected_type); #endif +/* make an MCS file out of a head */ +int g1m_make_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *rawhead); + /* open MCS head for decoding, correct it for encoding */ int g1m_decode_mcsfile_head(g1m_mcshead_t *head, int raw_type, const unsigned char *groupname, @@ -111,7 +114,7 @@ int g1m_decode_casfile_data(g1m_mcsfile_t **handle, /* 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); +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/buffer.h b/include/libg1m/buffer.h index c6c5e91..b5866f0 100644 --- a/include/libg1m/buffer.h +++ b/include/libg1m/buffer.h @@ -33,6 +33,9 @@ # include # include +/* ************************************************************************** */ +/* General definition */ +/* ************************************************************************** */ /* The callbacks types... */ typedef int (*g1m_buffer_read_t)(void*, unsigned char*, size_t); typedef int (*g1m_buffer_write_t)(void*, const unsigned char*, size_t); @@ -48,4 +51,42 @@ typedef struct { g1m_buffer_announce_t announce; } g1m_buffer_t; +/* ************************************************************************** */ +/* Memory buffer definition */ +/* ************************************************************************** */ +/* Cookie structure */ +typedef struct { + const unsigned char *p; + size_t left; +} g1m_cursor_t; + +/* Related callbacks and functions */ +int g1m_membuffer_read(void *cookie, unsigned char *dest, size_t size); + +/* ************************************************************************** */ +/* Limited buffer definition */ +/* ************************************************************************** */ +/* Cookie structure */ +typedef struct { + g1m_buffer_t *buffer; + size_t left; +} g1m_limited_t; + +/* Related functions and callbacks */ +int g1m_limbuffer_read(void *cookie, unsigned char *dest, size_t size); +int g1m_empty_limbuffer(g1m_buffer_t *limbuffer); + +/* ************************************************************************** */ +/* Buffer macros */ +/* ************************************************************************** */ +/* Initialize a memory buffer */ +# define g1m_membuffer(P, SZ) (g1m_buffer_t){ \ + .cookie = (g1m_cursor_t[]){{.p = (P), .left = (SZ)}}, \ + .read = g1m_membuffer_read} + +/* Initialize a limited buffer */ +# define g1m_limbuffer(BUFFER, SZ) (g1m_buffer_t){ \ + .cookie = (g1m_limited_t[]){{.buffer = (BUFFER), .left = (SZ)}}, \ + .read = g1m_limbuffer_read} + #endif /* LIBG1M_BUFFER_H */ diff --git a/include/libg1m/format/caspro.h b/include/libg1m/format/caspro.h index b1674f3..1bf13fd 100644 --- a/include/libg1m/format/caspro.h +++ b/include/libg1m/format/caspro.h @@ -47,8 +47,8 @@ struct caspro_header { uint8_t aux[8]; /* variable: "R\x0A"/"C\x0A", editor: password */ /* something else (?) */ - uint8_t nl[2]; /* 'NL' */ - uint8_t _ffs[11]; + uint8_t nl[2]; /* 'NL'? */ + uint8_t _reserved[11]; /* end of packet */ uint8_t checksum; diff --git a/include/libg1m/formatutils.h b/include/libg1m/formatutils.h index 9b5ce9b..48b0b14 100644 --- a/include/libg1m/formatutils.h +++ b/include/libg1m/formatutils.h @@ -28,21 +28,28 @@ # define LIBG1M_FORMATUTILS_H # include -/* get type */ +/* ************************************************************************** */ +/* General types (`g1m_t`) */ +/* ************************************************************************** */ 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, g1m_type_t *type); +/* ************************************************************************** */ +/* MCS types (`g1m_mcshead_t`/`g1m_mcsfile_t`) */ +/* ************************************************************************** */ /* get mcs type data */ -int g1m_maketype_mcs(const char *groupname, const char *filename, - unsigned int rawtype, g1m_mcstype_t *type, int *id); +int g1m_maketype_mcs(g1m_mcshead_t *head, + const char *groupname, const char *dirname, + const char *filename, unsigned int rawtype); /* get cas type data */ -int g1m_maketype_cas(const char *datatype, g1m_mcstype_t *type); +int g1m_maketype_cas(g1m_mcshead_t *head, + const char *datatype); /* get caspro type data */ -int g1m_maketype_caspro(const char *maintype, - const char *datatype, g1m_mcstype_t *type); +int g1m_maketype_caspro(g1m_mcshead_t *head, + const char *maintype, const char *datatype); #endif /* LIBG1M_FORMATUTILS_H */ diff --git a/include/libg1m/internals.h b/include/libg1m/internals.h index 19c8bf8..5c7d281 100644 --- a/include/libg1m/internals.h +++ b/include/libg1m/internals.h @@ -28,6 +28,8 @@ # include # include # include +# define MEMBUFFER(P, SZ) g1m_membuffer(P, SZ) +# define LIMBUFFER(BUFFER, SZ) g1m_limbuffer(BUFFER, SZ) /* ************************************************************************** */ /* Macros and platform-specific functions */ @@ -86,43 +88,6 @@ if (SKIP_err) return (SKIP_err); \ } -/* ************************************************************************** */ -/* Memory buffer-related */ -/* ************************************************************************** */ -/* Structure */ -typedef struct { - const unsigned char *p; - size_t left; -} g1m_cursor_t; - -/* Callbacks */ -int g1m_membuffer_read(void *cookie, unsigned char *dest, size_t size); - -/* Management functions */ -int g1m_empty_limbuffer(g1m_buffer_t *limbuffer); - -/* Initialize a memory buffer */ -# define MEMBUFFER(P, SZ) (g1m_buffer_t){ \ - .cookie = (g1m_cursor_t[]){{.p = (P), .left = (SZ)}}, \ - .read = g1m_membuffer_read} - -/* ************************************************************************** */ -/* Limited buffer */ -/* ************************************************************************** */ -/* Structure */ -typedef struct { - g1m_buffer_t *buffer; - size_t left; -} g1m_limited_t; - -/* Callbacks */ -int g1m_limbuffer_read(void *cookie, unsigned char *dest, size_t size); - -/* Initialize a limited buffer */ -# define LIMBUFFER(BUFFER, SZ) (g1m_buffer_t){ \ - .cookie = (g1m_limited_t[]){{.buffer = (BUFFER), .left = (SZ)}}, \ - .read = g1m_limbuffer_read} - /* ************************************************************************** */ /* Decoding functions */ /* ************************************************************************** */ @@ -158,10 +123,10 @@ int g1m_decode_fkey_cg_content(g1m_t *handle, g1m_buffer_t *buffer, /* MCS-specific decoding functions */ /* ************************************************************************** */ # define G1M_MCSFUNC(NAME) \ -int g1m_decode_mcs_##NAME(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, \ - uint_fast32_t length); +int g1m_decode_mcs_##NAME(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, \ + g1m_mcshead_t *head); -G1M_MCSFUNC(alphamem) +G1M_MCSFUNC(var) G1M_MCSFUNC(list) G1M_MCSFUNC(matrix) G1M_MCSFUNC(picture) @@ -178,7 +143,7 @@ G1M_MCSFUNC(string) malloc(sizeof(uint32_t*) * (H) + sizeof(uint32_t) * (W) * (H)) # define prepare_pixels(I, W, H) { \ uint32_t *PIXPREP_line = (uint32_t*)&(I)[(H)]; \ - for (int PIXPREP_y = 0; PIXPREP_y < (H); PIXPREP_y++) { \ + for (unsigned int PIXPREP_y = 0; PIXPREP_y < (H); PIXPREP_y++) { \ (I)[PIXPREP_y] = PIXPREP_line; \ PIXPREP_line += (W); \ }} diff --git a/include/libg1m/mcs.h b/include/libg1m/mcs.h index c7c89a8..ed6a173 100644 --- a/include/libg1m/mcs.h +++ b/include/libg1m/mcs.h @@ -43,23 +43,26 @@ typedef g1m_mcsfile_type_t g1m_mcstype_t; # define g1m_mcstype_ssheet 0x00000020 # define g1m_mcstype_string 0x00000040 # define g1m_mcstype_setup 0x00000080 -# define g1m_mcstype_alphamem 0x00000100 +# define g1m_mcstype_var 0x00000100 # define g1m_mcstype_vct 0x00000200 -# define g1m_mcstype_variable 0x00000400 -# define g1m_mcstype_end 0x00000800 +# define g1m_mcstype_end 0x00000400 /* MCS file type aliases */ # define g1m_mcstype_matrix g1m_mcstype_mat +# define g1m_mcstype_pic g1m_mcstype_pict # define g1m_mcstype_picture g1m_mcstype_pict # define g1m_mcstype_capture g1m_mcstype_capt # define g1m_mcstype_spreadsheet g1m_mcstype_ssheet # define g1m_mcstype_vector g1m_mcstype_vct +# define g1m_mcstype_alphamem g1m_mcstype_var +# define g1m_mcstype_variable g1m_mcstype_var +# define g1m_mcstype_variables g1m_mcstype_var /* Macros to check if the type uses the ID, and to interact with it */ -# define g1m_mcstype_uses_id(T) ((T) & (\ +# define g1m_mcshead_uses_id(H) (((H)->type & (\ g1m_mcstype_list | g1m_mcstype_mat | g1m_mcstype_vct | \ - g1m_mcstype_pict | g1m_mcstype_capt | g1m_mcstype_string | \ - g1m_mcstype_variable)) + g1m_mcstype_pict | g1m_mcstype_capt | g1m_mcstype_string) || \ + ((H)->type == g1m_mcstype_var && (H)->count == 1))) # define g1m_get_id_major(I) ((I) >> 5) # define g1m_get_id_minor(I) ((I) & 31) @@ -77,8 +80,16 @@ 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 */ +# define g1m_mcsflag_unfinished 0x8000 /* is there still parts to read? */ +# define g1m_mcsflag_complex 0x0001 /* is a complex variable */ + +/* mcs file type -- what type of raw information is there + * e.g. `head.flags & g1m_mcsmask_info == g1m_mcsinfo_g1m` */ +# define g1m_mcsmask_info 0x6000 +# define g1m_mcsinfo_none 0x0000 +# define g1m_mcsinfo_mcs 0x2000 +# define g1m_mcsinfo_cas 0x4000 +# define g1m_mcsinfo_caspro 0x6000 /* mcs file head */ typedef struct g1m_mcshead_s { @@ -105,8 +116,8 @@ typedef struct g1m_mcshead_s { } g1m_mcshead_t; /* mcs file */ -# define g1m_has_password(F) (F)->password[0] -# define g1m_remove_password(F) (F)->password[0] = 0 +# define g1m_has_password(F) (F)->head.password[0] +# define g1m_remove_password(F) (F)->head.password[0] = 0 typedef struct g1m_mcsfile_s { /* head */ g1m_mcshead_t head; @@ -114,16 +125,14 @@ typedef struct g1m_mcsfile_s { /* content (useful when not read) */ char *content; - /* for spreadsheets, lists and matrixes */ - g1m_mcs_cell_t **cells; - /* variables */ g1m_mcs_cell_t var; g1m_mcs_cell_t *vars; + g1m_mcs_cell_t **cells; /* for pictures and captures */ - uint32_t **image; /* 0x0RGB */ - uint32_t **second_image; /* 0x0RGB */ + uint32_t **pic; /* 0x0RGB */ + uint32_t ***pics; } g1m_mcsfile_t; #endif /* LIBG1M_MCS_H */ diff --git a/src/core/free.c b/src/core/free.c index 6743c3d..4fc5d12 100644 --- a/src/core/free.c +++ b/src/core/free.c @@ -65,14 +65,16 @@ void g1m_free_mcsfile_content(g1m_mcsfile_t *handle) } /* free the images */ - if (type & (g1m_mcstype_pict | g1m_mcstype_capt)) { - free(handle->image); - if (type & g1m_mcstype_pict) - free(handle->second_image); + if (type & g1m_mcstype_pict) { + for (int i = 0; i < handle->head.count; i++) + free(handle->pics[i]); + if (handle->pics != &handle->pic) + free(handle->pics); } /* free the vars */ - if (type & g1m_mcstype_alphamem) + if ((type & g1m_mcstype_alphamem) + && handle->vars != &handle->var) free(handle->vars); /* free the content */ diff --git a/src/decode/cas.c b/src/decode/cas.c index 7ea4395..96412a2 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_maketype_cas(datatype, &head->type)) + if (g1m_maketype_cas(head, datatype)) return (g1m_error_unrecognized); /* fill the handle */ diff --git a/src/decode/casemul.c b/src/decode/casemul.c index e8d6862..de8d49a 100644 --- a/src/decode/casemul.c +++ b/src/decode/casemul.c @@ -138,31 +138,22 @@ static int read_picture(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, uint8_t rawpx[total]; READ(rawpx, total) uint8_t *px = rawpx; - /* allocate the file */ - g1m_mcsfile_t *file = malloc(sizeof(g1m_mcsfile_t)); - if (!file) return (g1m_error_alloc); - memset(file, 0, sizeof(g1m_mcsfile_t)); - - /* make the pixels */ - int width = pct.width, height = pct.height; - uint32_t **img = alloc_pixels(width, height); - if (!img) { free(file); return (g1m_error_alloc); } - - /* set the head */ - file->head.type = g1m_mcstype_capt; - memcpy(file->head.name, name, strlen(name) + 1); + /* make the head and allocate file */ + g1m_mcshead_t head = { + .type = g1m_mcstype_capture, + .width = pct.width, .height = pct.height, + }; + memcpy(head.name, name, strlen(name) + 1); /* TODO: id */ + err = g1m_make_mcsfile(pfile, &head); + if (err) return (err); /* set the pixels */ - prepare_pixels(img, width, 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++) + uint32_t **img = (*pfile)->pics[0]; + for (int x = 0; x < pct.width; x++) for (int y = 0; y < pct.height; y++) img[y][x] = colours[*px++]; /* finish */ - *pfile = file; return (0); } @@ -179,8 +170,7 @@ static int read_picture(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, static int read_matrix(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, int big_endian) { - int err; - + int err; *pfile = NULL; /* general record things */ char name[13]; uint_fast32_t record_length; if ((err = read_top(buffer, name, &record_length)) @@ -198,52 +188,38 @@ static int read_matrix(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, double tab[total]; READ(tab, total * sizeof(double)) double *raw = tab; - /* allocate handle */ - g1m_mcsfile_t *file = malloc(sizeof(g1m_mcsfile_t)); - if (!file) return (g1m_error_alloc); - memset(file, 0, sizeof(g1m_mcsfile_t)); - - /* allocate matrix */ - file->cells = malloc(sizeof(g1m_mcs_cell_t*) * height); - if (!file->cells) { free(file); return (g1m_error_alloc); } - g1m_mcs_cell_t *rws = malloc(sizeof(g1m_mcs_cell_t) * height * width); - if (!rws) { free(file); free(file->cells); return (g1m_error_alloc); } - - /* set the information */ - file->head.type = g1m_mcstype_mat; - memcpy(file->head.name, name, strlen(name) + 1); + /* make the head and allocate file */ + g1m_mcshead_t head = { + .type = g1m_mcstype_matrix, + .width = width, .height = height, + }; + memcpy(head.name, name, strlen(name) + 1); /* TODO: id */ + err = g1m_make_mcsfile(pfile, &head); + if (err) return (err); /* read the matrix */ - 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]; - - /* read column */ - for (int x = 0; x < width; x++) { - /* read the bcd */ - g1m_bcd_t bcd; g1m_bcd_fromdouble(*raw++, &bcd); + g1m_mcs_cell_t **cells = (*pfile)->cells; + for (int y = 0; y < height; y++) 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); + /* 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 = {}, - .used = 1 - }; - } + /* make the cell */ + cells[y][x] = (g1m_mcs_cell_t){ + .real = bcd, + .imgn = {}, + .used = 1 + }; } /* no error */ - *pfile = file; return (0); } @@ -260,8 +236,7 @@ static int read_matrix(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, static int read_list(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, int big_endian) { - int err; - + int err; *pfile = NULL; /* general record things */ char name[13]; uint_fast32_t record_length; if ((err = read_top(buffer, name, &record_length)) @@ -277,28 +252,20 @@ static int read_list(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, double tab[len]; READ(tab, len * sizeof(double)) double *raw = tab; - /* allocate handle */ - g1m_mcsfile_t *file = malloc(sizeof(g1m_mcsfile_t)); - if (!file) return (g1m_error_alloc); - memset(file, 0, sizeof(g1m_mcsfile_t)); - - /* allocate matrix */ - file->cells = malloc(sizeof(g1m_mcs_cell_t*) * len); - if (!file->cells) { free(file); return (g1m_error_alloc); } - g1m_mcs_cell_t *rws = malloc(sizeof(g1m_mcs_cell_t) * len); - if (!rws) { free(file->cells); free(file); return (g1m_error_alloc); } - - /* set the information */ - file->head.type = g1m_mcstype_list; - memcpy(file->head.name, name, strlen(name) + 1); + /* make head */ + g1m_mcshead_t head = { + .type = g1m_mcstype_list, + .width = 1, .height = len + }; + memcpy(head.name, name, strlen(name) + 1); /* TODO: id */ + err = g1m_make_mcsfile(pfile, &head); + if (err) return (err); /* read the list */ - file->head.width = 1; - file->head.height = len; + g1m_mcs_cell_t **cells = (*pfile)->cells; for (int x = 0; x < len; x++) { - /* correct matrix, read bcd */ - file->cells[x] = &rws[x]; + /* read bcd */ g1m_bcd_t bcd; g1m_bcd_fromdouble(*raw++, &bcd); #if LOGLEVEL <= ll_info @@ -309,7 +276,7 @@ static int read_list(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, #endif /* set the cell */ - file->cells[x][0] = (g1m_mcs_cell_t){ + cells[x][0] = (g1m_mcs_cell_t){ .real = bcd, .imgn = {}, .used = 1 @@ -317,7 +284,6 @@ static int read_list(g1m_mcsfile_t **pfile, g1m_buffer_t *buffer, } /* no error */ - *pfile = file; return (0); } diff --git a/src/decode/caspro.c.draft b/src/decode/caspro.c similarity index 62% rename from src/decode/caspro.c.draft rename to src/decode/caspro.c index 61dbde2..d4eaee9 100644 --- a/src/decode/caspro.c.draft +++ b/src/decode/caspro.c @@ -21,6 +21,9 @@ * ************************************************************************** */ #include +/* ************************************************************************** */ +/* Head decoding function */ +/* ************************************************************************** */ /** * g1m_decode_caspro_head: * Decode a CASIOLINK Protocol header. @@ -32,10 +35,28 @@ 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 */ + if (head->type == 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; + } + /* TODO */ - return (g1m_error_unknown); + return (0); } +/* ************************************************************************** */ +/* Part decoding function */ +/* ************************************************************************** */ /** * g1m_decode_caspro_part: * Decode a CASIOLINK Protocol content part. @@ -47,8 +68,7 @@ int g1m_decode_caspro_head(g1m_mcshead_t *head, g1m_buffer_t *buffer) * @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) +int g1m_decode_caspro_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer) { /* TODO */ return (g1m_error_unknown); diff --git a/src/decode/mcs/list.c b/src/decode/mcs/list.c index b887c82..b309282 100644 --- a/src/decode/mcs/list.c +++ b/src/decode/mcs/list.c @@ -22,94 +22,68 @@ * g1m_decode_mcs_list: * Decode an List. * - * @arg handle the handle. + * @arg handle the handle to make. * @arg buffer the buffer to read from. - * @arg size the length. + * @arg head the pre-filled head to complete and use. * @return the error code (0 if ok). */ -int g1m_decode_mcs_list(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, - uint_fast32_t size) +int g1m_decode_mcs_list(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, + g1m_mcshead_t *head) { /* read header */ DREAD(hd, mcs_listheader) - - /* correct endianess */ uint_fast16_t elcount = be16toh(hd.element_count); - - /* log */ log_info("Title is '%.8s'", hd.title); - /* prepare browsing */ - size -= sizeof(struct mcs_listheader); + /* make final head */ + head->width = 1; + head->height = elcount; + int err = g1m_make_mcsfile(handle, head); + if (err) return (err); - /* make tabs */ - g1m_bcd_t real[elcount], imgn[elcount]; - if (elcount) { - int one_imgn = 0; - mcs_bcd_t tab[elcount]; - /* read the real parts */ - size_t elsize = sizeof(mcs_bcd_t) * elcount; - size -= elsize; { - /* read reals */ - READ(tab, elsize) + /* main copying loop */ + g1m_mcs_cell_t **tab = (*handle)->cells; int one_imgn = 0; + for (uint_fast32_t y = 0; y < elcount; y++) { + g1m_bcd_t bcd; GDREAD(rawbcd, bcd) + one_imgn |= g1m_bcd_frommcs(&rawbcd, &bcd); - /* convert them */ - for (uint_fast16_t i = 0; i < elcount; i++) - one_imgn |= g1m_bcd_frommcs(&tab[i], &real[i]); - } + /* prepare index and store */ + tab[y][0] = (g1m_mcs_cell_t){ + .real = bcd, + .imgn = {}, + .used = 1 + }; + } - /* read the imaginary parts */ - if (one_imgn) { - READ(tab, elsize) - - /* convert */ - for (uint_fast16_t i = 0; i < elcount; i++) - g1m_bcd_frommcs(&tab[i], &imgn[i]); + /* main copying loop for imaginary parts */ + if (one_imgn) for (uint_fast32_t y = 0; y < elcount; y++) { + g1m_bcd_t bcd; GDREAD(rawbcd, bcd) + if (g1m_bcd_has_special(&tab[y][0].real)) { + g1m_bcd_frommcs(&rawbcd, &bcd); + tab[y][0].imgn = bcd; } } - /* fill final tab */ - handle->head.height = elcount; - handle->head.width = 1; - handle->cells = NULL; - if (elcount) { -#if LOGLEVEL >= ll_info - char rbuf[G1M_BCD_GOODBUFSIZE], ibuf[G1M_BCD_GOODBUFSIZE]; -#endif - - /* allocate final tab */ - g1m_mcs_cell_t **tab = malloc(sizeof(g1m_mcs_cell_t*) * elcount); - if (!tab) return (g1m_error_alloc); - g1m_mcs_cell_t *rws = malloc(sizeof(g1m_mcs_cell_t) * elcount); - if (!tab) { free(tab); return (g1m_error_alloc); } - - /* main copying loop */ - for (uint_fast32_t y = 0; y < elcount; y++) { - int has_complex = g1m_bcd_has_special(&real[y]); - - /* prepare index and store */ - tab[y] = &rws[y]; - tab[y][0] = (g1m_mcs_cell_t){ - .used = 1, - .real = real[y], - .imgn = has_complex ? imgn[y] : (g1m_bcd_t){} - }; - -#if LOGLEVEL >= ll_info - g1m_bcdtoa(&tab[y][0].real, rbuf, G1M_BCD_GOODBUFSIZE); - if (has_complex) { - g1m_bcdtoa(&tab[y][0].imgn, ibuf, G1M_BCD_GOODBUFSIZE); - log_info("[%" PRIuFAST32 "] %si + %s", y, ibuf, rbuf); - } else - log_info("[%" PRIuFAST32 "] %s", y, rbuf); -#endif - } - - /* don't forget your baguette! */ - handle->cells = tab; +#if LOGLEVEL <= ll_info + /* logging loop */ + char rbuf[G1M_BCD_GOODBUFSIZE], ibuf[G1M_BCD_GOODBUFSIZE]; + for (uint_fast32_t y = 0; y < elcount; y++) { + g1m_bcdtoa(&tab[y][0].real, rbuf, G1M_BCD_GOODBUFSIZE); + if (g1m_bcd_has_special(&tab[y][0].real)) { + g1m_bcdtoa(&tab[y][0].imgn, ibuf, G1M_BCD_GOODBUFSIZE); + log_info("[%" PRIuFAST32 "] %si + %s", y, ibuf, rbuf); + } else + log_info("[%" PRIuFAST32 "] %s", y, rbuf); } +#endif /* no error */ return (0); + + /* in case */ +fail: + g1m_free_mcsfile(*handle); + *handle = NULL; + return (err); } diff --git a/src/decode/mcs/matrix.c b/src/decode/mcs/matrix.c index 0c52b3b..7ae493c 100644 --- a/src/decode/mcs/matrix.c +++ b/src/decode/mcs/matrix.c @@ -22,22 +22,19 @@ * g1m_decode_mcs_matrix: * Decode a matrix. * - * @arg handle the handle. + * @arg handle the handle to make. * @arg buffer the buffer to read from. - * @arg length the data length. + * @arg head the pre-filled head to complete and use. * @return the error code (0 if ok). */ -int g1m_decode_mcs_matrix(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, - uint_fast32_t length) +int g1m_decode_mcs_matrix(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, + g1m_mcshead_t *head) { - g1m_mcs_cell_t **tab, *rws; int err = g1m_error_alloc; /* read header */ DREAD(hd, mcs_matheader) - - /* correct endianess */ hd.width = be16toh(hd.width); hd.height = be16toh(hd.height); @@ -45,62 +42,58 @@ int g1m_decode_mcs_matrix(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, uint_fast32_t w = hd.width, h = hd.height; log_info("Matrix size is %" PRIuFAST32 "*%" PRIuFAST32, w, h); - /* store dimensions */ - handle->head.width = w; - handle->head.height = h; - handle->cells = NULL; + /* make final head */ + head->width = w; + head->height = h; + if ((err = g1m_make_mcsfile(handle, head))) + return (err); - if (w && h) { - /* alloc real matrix */ - tab = malloc(sizeof(g1m_mcs_cell_t*) * h); - if (!tab) return (g1m_error_alloc); - rws = malloc(sizeof(g1m_mcs_cell_t) * h * w); - if (!rws) { free(tab); return (g1m_error_alloc); } + /* main copying loop */ + g1m_mcs_cell_t **tab = (*handle)->cells; int one_imgn = 0; + for (uint_fast32_t y = 0; y < h; y++) + for (uint_fast32_t x = 0; x < w; x++) { + /* read the cell */ + g1m_bcd_t bcd; GDREAD(rawbcd, bcd) + one_imgn |= g1m_bcd_frommcs(&rawbcd, &bcd); - /* copy */ - int one_imgn = 0; - g1m_bcd_t bcd; - for (uint_fast32_t y = 0; y < h; y++) { - /* prepare index */ - tab[y] = &rws[y * w]; - - /* read squares */ - for (uint_fast32_t x = 0; x < w; x++) { - /* read the cell */ - GDREAD(rawbcd, bcd) - one_imgn |= g1m_bcd_frommcs(&rawbcd, &bcd); - - /* store it */ - tab[y][x] = (g1m_mcs_cell_t){ - .real = bcd, - .imgn = {}, - .used = 1 - }; - } - } - - /* check imaginary parts */ - if (one_imgn) { - for (uint_fast32_t y = 0; y < h; y++) - for (uint_fast32_t x = 0; x < w; x++) { - GDREAD(rawbcd, bcd) - if (g1m_bcd_has_special(&tab[y][x].real)) { - g1m_bcd_frommcs(&rawbcd, &bcd); - tab[y][x].imgn = bcd; - } - } - } - - /* your sandwich, monsieur. */ - handle->cells = tab; + /* store it */ + tab[y][x] = (g1m_mcs_cell_t){ + .real = bcd, + .imgn = {}, + .used = 1 + }; } + /* check imaginary parts */ + if (one_imgn) for (uint_fast32_t y = 0; y < h; y++) + for (uint_fast32_t x = 0; x < w; x++) { + g1m_bcd_t bcd; GDREAD(rawbcd, bcd) + if (g1m_bcd_has_special(&tab[y][x].real)) { + g1m_bcd_frommcs(&rawbcd, &bcd); + tab[y][x].imgn = bcd; + } + } + +#if LOGLEVEL <= ll_info + /* logging loop */ + char rbuf[G1M_BCD_GOODBUFSIZE], ibuf[G1M_BCD_GOODBUFSIZE]; + for (uint_fast32_t y = 0; y < h; y++) + for (uint_fast32_t x = 0; x < w; x++) { + g1m_bcdtoa(&tab[y][x].real, rbuf, G1M_BCD_GOODBUFSIZE); + if (g1m_bcd_has_special(&tab[y][x].real)) { + g1m_bcdtoa(&tab[y][x].imgn, ibuf, G1M_BCD_GOODBUFSIZE); + log_info("[%" PRIuFAST32 "] %si + %s", y, ibuf, rbuf); + } else + log_info("[%" PRIuFAST32 "] %s", y, rbuf); + } +#endif + /* no error */ return (0); /* in case of unexpected EOF */ fail: - free(tab); - free(rws); + g1m_free_mcsfile(*handle); + *handle = NULL; return (err); } diff --git a/src/decode/mcs/picture.c b/src/decode/mcs/picture.c index 2303b6c..98c1c18 100644 --- a/src/decode/mcs/picture.c +++ b/src/decode/mcs/picture.c @@ -31,7 +31,7 @@ * @arg height the image height. */ -static int get_image(g1m_buffer_t *buffer, uint32_t ***img, +static int get_image(g1m_buffer_t *buffer, uint32_t **image, unsigned int width, unsigned int height) { /* get raw pixels */ @@ -40,18 +40,8 @@ static int get_image(g1m_buffer_t *buffer, uint32_t ***img, uint8_t buf[bufsize]; READ(buf, bufsize) - /* alloc */ - *img = malloc(height * (sizeof(uint32_t*)) - + width * height * sizeof(uint32_t)); - if (!*img) - return (g1m_error_alloc); - /* fill */ - uint32_t **image = *img; for (uint_fast16_t y = 0; y < height; y++) { - /* setup index */ - image[y] = (uint32_t*)&image[height] + y * width; - /* init vars for monochrome with fill bits image browsing */ uint8_t *b = &buf[y * linesize]; int bit = 1 << 7; @@ -78,65 +68,72 @@ static int get_image(g1m_buffer_t *buffer, uint32_t ***img, * g1m_decode_mcs_capture: * Decode a capture. * - * @arg handle the handle. + * @arg handle the handle to make. * @arg buffer the buffer to read from. - * @arg length the data length. + * @arg head the pre-filled head to complete and use. * @return the error code (0 if ok). */ -int g1m_decode_mcs_capture(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, - uint_fast32_t length) +int g1m_decode_mcs_capture(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, + g1m_mcshead_t *head) { /* read header */ DREAD(hd, mcs_captureheader) - - /* correct endianess */ hd.width = be16toh(hd.width); hd.height = be16toh(hd.height); - /* store */ - handle->head.width = hd.width; - handle->head.height = hd.height; + /* make final head and file */ + head->width = hd.width; + head->height = hd.height; + int err = g1m_make_mcsfile(handle, head); + if (err) return (err); /* print info */ - log_info("capture is %dx%d sized", handle->head.width, handle->head.height); + g1m_mcsfile_t *h = *handle; + log_info("capture is %dx%d sized", h->head.width, h->head.height); /* get the image and return */ - return (get_image(buffer, &handle->image, - handle->head.width, handle->head.height)); + err = get_image(buffer, h->pics[0], h->head.width, h->head.height); + if (err) { g1m_free_mcsfile(*handle); free(*handle); } + return (err); } /** * g1m_decode_mcs_picture: * Decode a picture. * - * @arg handle the handle. + * @arg handle the handle to make. * @arg buffer the buffer to read from. - * @arg length the data length. + * @arg head the pre-filled head to complete and use. * @return the error code (0 if ok). */ -int g1m_decode_mcs_picture(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, - uint_fast32_t length) +int g1m_decode_mcs_picture(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, + g1m_mcshead_t *head) { - int err; - - /* store some dimensions, in case. */ - handle->head.width = 128; - handle->head.height = 64; + /* make final head */ + head->width = 128; + head->height = 64; + int err = g1m_make_mcsfile(handle, head); + if (err) return (err); /* get the first image */ - if ((err = get_image(buffer, &handle->image, 128, 64))) { + g1m_mcsfile_t *h = *handle; + if ((err = get_image(buffer, h->pics[0], 128, 64))) { log_fatal("Failed to get the first image."); - return (err); + goto fail; } /* and the second */ - if ((err = get_image(buffer, &handle->second_image, 128, 64))) { + if ((err = get_image(buffer, h->pics[1], 128, 64))) { log_fatal("Failed to get the second image."); - return (err); + goto fail; } /* no error */ return (0); +fail: + g1m_free_mcsfile(*handle); + *handle = NULL; + return (err); } diff --git a/src/decode/mcs/program.c b/src/decode/mcs/program.c index 1683a14..7179e4b 100644 --- a/src/decode/mcs/program.c +++ b/src/decode/mcs/program.c @@ -22,34 +22,39 @@ * g1m_decode_mcs_program: * Decode a program. * - * @arg handle the handle. + * @arg handle the handle to make. * @arg buffer the buffer to read from. - * @arg length the data length. + * @arg head the pre-filled head to complete and use. * @return the error code (0 if ok). */ -int g1m_decode_mcs_program(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, - uint_fast32_t length) +int g1m_decode_mcs_program(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, + g1m_mcshead_t *head) { + int err; + /* read header */ DREAD(hd, mcs_programheader) - - /* print header data */ log_info("Program password is '%.8s'.", hd.password); - /* store info */ - strncpy(handle->head.password, (char*)hd.password, 8); - handle->head.password[8] = 0; + /* make final head and file */ + strncpy(head->password, (char*)hd.password, 8); + head->password[8] = 0; + head->size -= sizeof(struct mcs_programheader); + head->size += 1; /* terminating zero - XXX: keep it? */ + err = g1m_make_mcsfile(handle, head); + if (err) return (err); /* get content */ - size_t content_size = length - sizeof(struct mcs_programheader); - log_info("Getting program content (%" PRIuSIZE "o)", content_size); - handle->content = malloc(content_size + 1); - handle->head.size = content_size + 1; - if (!handle->content) return (g1m_error_alloc); - READ(handle->content, content_size); - handle->content[content_size] = 0; + g1m_mcsfile_t *h = *handle; + log_info("Getting program content (%" PRIuSIZE "o)", head->size); + GREAD(h->content, head->size - 1); + h->content[head->size] = 0; /* no error */ return (0); +fail: + g1m_free_mcsfile(*handle); + *handle = NULL; + return (err); } diff --git a/src/decode/mcs/setup.c b/src/decode/mcs/setup.c index 815ad68..66f4021 100644 --- a/src/decode/mcs/setup.c +++ b/src/decode/mcs/setup.c @@ -22,18 +22,18 @@ * g1m_decode_mcs_setup: * Decode settings. * - * @arg handle the handle. + * @arg handle the handle to make. * @arg buffer the buffer to read from. - * @arg length the data length. + * @arg head the pre-filled head to complete and use. * @return the error code (0 if ok). */ -int g1m_decode_mcs_setup(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, - uint_fast32_t length) +int g1m_decode_mcs_setup(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, + g1m_mcshead_t *head) { (void)handle; log_info("Settings MCS file is not managed yet."); /* TODO */ - SKIP(length) - return (0); + SKIP(head->size) + return (g1m_make_mcsfile(handle, head)); } diff --git a/src/decode/mcs/spreadsheet.c b/src/decode/mcs/spreadsheet.c index 1dfe063..feb6fba 100644 --- a/src/decode/mcs/spreadsheet.c +++ b/src/decode/mcs/spreadsheet.c @@ -22,26 +22,22 @@ * g1m_decode_mcs_spreadsheet: * Decode a spreadsheet. * - * @arg handle the handle. + * @arg handle the handle to make. * @arg buffer the buffer to read from. - * @arg length the data length. + * @arg head the pre-filled head to complete and use. * @return the error code (0 if ok). */ -int g1m_decode_mcs_spreadsheet(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, - uint_fast32_t length) +int g1m_decode_mcs_spreadsheet(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, + g1m_mcshead_t *head) { /* read header */ DREAD(hd, mcs_spreadsheetheader) - - /* check if the spreadsheet type is known */ if (hd.has_subheader != 0x01) return (0); /* read subheader */ DREAD(shd, mcs_spreadsheet_subheader) - - /* correct endianness */ uint_fast32_t colcount = hd.column_count; colcount = be32toh(colcount << 8); shd.defs_size = be32toh(shd.defs_size); @@ -108,32 +104,16 @@ int g1m_decode_mcs_spreadsheet(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, rows++, cols++; /* create final tab */ - handle->cells = NULL; - handle->head.width = 0; - handle->head.height = 0; - if (cells_count) { - handle->head.width = cols; - handle->head.height = rows; + head->width = 0; head->height = 0; + if (cells_count) { head->width = cols; head->height = rows; } + int err = g1m_make_mcsfile(handle, head); + if (err) return (err); - /* alloc */ - g1m_mcs_cell_t **tab = malloc(sizeof(g1m_mcs_cell_t*) * cols); - if (!tab) return (g1m_error_alloc); - g1m_mcs_cell_t *rws = malloc(sizeof(g1m_mcs_cell_t) * cols * rows); - if (!rws) { free(tab); return (g1m_error_alloc); } - - /* main copying loop */ - for (uint_fast32_t y = 0; y < cols; y++) { - /* prepare index */ - tab[y] = &rws[y * rows]; - - /* copy each cell */ - for (uint_fast32_t x = 0; x < rows; x++) - tab[y][x] = cells[x * 1000 + y]; - } - - /* i used to be a cow. */ - handle->cells = tab; - } + /* main copying loop */ + g1m_mcs_cell_t **tab = (*handle)->cells; + for (uint_fast32_t y = 0; y < head->height; y++) + for (uint_fast32_t x = 0; x < head->width; x++) + tab[y][x] = cells[x * 1000 + y]; /* no error */ return (0); diff --git a/src/decode/mcs/string.c b/src/decode/mcs/string.c index bb74fbd..d1ad909 100644 --- a/src/decode/mcs/string.c +++ b/src/decode/mcs/string.c @@ -22,20 +22,22 @@ * g1m_decode_mcs_string: * Decode an MCS string. * - * @arg handle the handle. + * @arg handle the handle to make. * @arg buffer the buffer to read from. - * @arg length the data length. + * @arg head the pre-filled head to complete and use. * @return the error code (0 if ok). */ -int g1m_decode_mcs_string(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, - uint_fast32_t length) +int g1m_decode_mcs_string(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, + g1m_mcshead_t *head) { (void)handle; + + /* print content */ log_info("String MCS file is not managed yet. Content:"); - uint8_t str[length]; - READ(str, length); + uint_fast32_t length = head->size; + uint8_t str[length]; READ(str, length); logm_info(str, length); - /* TODO */ - return (0); + + return (g1m_make_mcsfile(handle, head)); } diff --git a/src/decode/mcs/alphamem.c b/src/decode/mcs/var.c similarity index 54% rename from src/decode/mcs/alphamem.c rename to src/decode/mcs/var.c index ee68d36..c49c7ee 100644 --- a/src/decode/mcs/alphamem.c +++ b/src/decode/mcs/var.c @@ -1,5 +1,5 @@ /* ***************************************************************************** - * decode/mcs/alphamem.c -- decode an MCS alpha memory file. + * decode/mcs/var.c -- decode an MCS variable/alpha memory file. * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey * * This file is part of libg1m. @@ -19,50 +19,37 @@ #include /** - * g1m_decode_mcs_alphamem: + * g1m_decode_mcs_var: * Decode alpha memory (variables). * - * @arg handle the handle. + * @arg handle the handle to make. * @arg buffer the buffer to read from. - * @arg length the data length. + * @arg head the pre-filled head to complete and use. * @return the error code (0 if ok). */ -int g1m_decode_mcs_alphamem(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, - uint_fast32_t length) +int g1m_decode_mcs_var(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, + g1m_mcshead_t *head) { /* read the data */ + uint_fast32_t length = head->size; uint8_t buf[length]; READ(buf, length) - /* 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->head.count * sizeof(g1m_mcs_cell_t)); - if (!handle->vars) return (g1m_error_alloc); + /* complete header */ + head->count = length / (2 * sizeof(mcs_bcd_t)); + int err = g1m_make_mcsfile(handle, head); + if (err) return (err); + g1m_mcsfile_t *h = *handle; /* copy */ const mcs_bcd_t *b = (void*)buf; - 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; + for (int i = 0; i < head->count; i++) { + g1m_bcd_frommcs(b++, &h->vars[i].real); + g1m_bcd_frommcs(b++, &h->vars[i].imgn); + h->vars[i].used = 1; } - /* copy */ - size_t tocopy = length - length % sizeof(g1m_mcs_cell_t); - memcpy(handle->vars, buf, tocopy); - /* no problem, woop woop */ return (0); } diff --git a/src/decode/std/mcs.c b/src/decode/std/mcs.c index 7d34e31..bb313d7 100644 --- a/src/decode/std/mcs.c +++ b/src/decode/std/mcs.c @@ -24,7 +24,8 @@ /* Type correspondance list */ /* ************************************************************************** */ /* MCS file parsing function type */ -typedef int (*mcs_decode_func_t)(g1m_mcsfile_t*, g1m_buffer_t*, uint_fast32_t); +typedef int (*mcs_decode_func_t)(g1m_mcsfile_t**, g1m_buffer_t*, + g1m_mcshead_t*); /* Correspondance type */ struct mcs_corresp { @@ -43,8 +44,7 @@ static struct mcs_corresp mcs_types[] = { {g1m_mcstype_capt, FUNC(capture)}, {g1m_mcstype_string, FUNC(string)}, {g1m_mcstype_setup, FUNC(setup)}, - {g1m_mcstype_alphamem, FUNC(alphamem)}, - {g1m_mcstype_variable, FUNC(alphamem)}, + {g1m_mcstype_alphamem, FUNC(var)}, {} }; @@ -93,30 +93,19 @@ int g1m_decode_mcsfile_head(g1m_mcshead_t *head, { /* check that we have a head, lol */ if (!head) return (-1); + head->size = filesize; /* look for the raw type */ - if (g1m_maketype_mcs((char*)groupname, (char*)filename, raw_type, - &head->type, &head->id)) - head->type = g1m_mcstype_unknown; + g1m_maketype_mcs(head, (char*)groupname, (char*)dirname, + (char*)filename, raw_type); log_info("libg1m file type is 0x%08" PRIXMCSTYPE, head->type); #if LOGLEVEL <= ll_info - if (g1m_mcstype_uses_id(head->type)) { + if (g1m_mcshead_uses_id(head)) { log_info("libg1m file id is (%d, %d)", g1m_get_id_major(head->id), g1m_get_id_minor(head->id)); } #endif - /* copy the name and size */ - memcpy(head->name, filename, 8); head->name[8] = 0; - head->size = filesize; - - /* save raw data */ - head->_rawtype = raw_type; - memcpy(head->_group, groupname, 16); head->_group[16] = 0; - if (dirname) { - memcpy(head->_dirname, dirname, 8); head->_dirname[8] = 0; - } else memset(head->_dirname, 0, 9); - /* everything went well! */ return (0); } @@ -144,15 +133,7 @@ int g1m_decode_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *head, /* check that the head is there */ if (!head) return (g1m_error_op); - - /* create handle */ - *handle = malloc(sizeof(g1m_mcsfile_t)); - if (!handle) return (g1m_error_alloc); - g1m_mcsfile_t *h = *handle; - memset(h, 0, sizeof(g1m_mcsfile_t)); - - /* copy the head */ - memcpy(&h->head, head, sizeof(g1m_mcshead_t)); + g1m_mcshead_t h = *head; /* look for the parsing function */ mcs_decode_func_t decode = lookup_mcsfile_decode(head->type); @@ -161,42 +142,35 @@ int g1m_decode_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *head, goto notparsing; } - /* read the buffer (safer) */ - uint8_t *buf = malloc(head->size); - if (!buf) return (g1m_error_alloc); - READ(buf, head->size) - /* decode */ - g1m_buffer_t membuf = MEMBUFFER(buf, head->size); - err = (*decode)(h, &membuf, head->size); - free(buf); - if (err) goto fail; + if (!head->size) err = (*decode)(handle, buffer, &h); + else { + g1m_buffer_t lbuf = LIMBUFFER(buffer, head->size); + err = (*decode)(handle, &lbuf, &h); + if (lbuf._offset < head->size) SKIP(head->size - lbuf._offset) + } - /* no error :D */ + /* oh yeah, and go away. */ + if (err) goto fail; return (0); notparsing: /* allocate enough space */ - h->content = malloc(head->size); - err = g1m_error_alloc; - if (!h->content) goto fail; + if ((err = g1m_make_mcsfile(handle, &h))) + return (err); /* read the content */ - GREAD(h->content, head->size) + GREAD((*handle)->content, h.size) /* log */ log_info("File content:"); - logm_info(h->content, head->size); + logm_info((*handle)->content, h.size); /* saved normally */ return (0); fail: - if (h) { - if (h->content) free(h->content); - free(h); - } - *handle = NULL; + g1m_free_mcsfile(*handle); return (err); } @@ -263,8 +237,6 @@ int g1m_decode_std_mcs(g1m_t *handle, g1m_buffer_t *buffer, for (uint_fast32_t i = 0; i < hd.subcount; i++) { /* get the part header */ GDREAD(fhd, mcs_fileheader) - - /* correct endianess */ fhd.datalength = be32toh(fhd.datalength); /* log info about the subpart */ diff --git a/src/decode/std/picture.c b/src/decode/std/picture.c index 2efe2fa..83f1333 100644 --- a/src/decode/std/picture.c +++ b/src/decode/std/picture.c @@ -122,7 +122,7 @@ int g1m_decode_std_g3p(g1m_t *handle, g1m_buffer_t *buffer, } /* allocate picture in handle */ - int w = ihd.width, h = ihd.height; + unsigned int w = ihd.width, h = ihd.height; handle->width = w; handle->height = h; handle->pixels = alloc_pixels(w, h); diff --git a/src/manage/mcs.c.draft b/src/manage/mcs.c similarity index 55% rename from src/manage/mcs.c.draft rename to src/manage/mcs.c index 9bcc899..308c312 100644 --- a/src/manage/mcs.c.draft +++ b/src/manage/mcs.c @@ -19,6 +19,108 @@ #include #define MCS_CHUNK_SIZE 16 +/* ************************************************************************** */ +/* Allocate files and content */ +/* ************************************************************************** */ +/** + * g1m_make_mcsfile: + * Make an MCS file out of a head. + * + * Will allocate all of the required parts of the MCS file for it to be + * filled later. + * + * @arg handle the file to allocate. + * @arg rawhead the head to use. + * @return the error (if any). + */ + +int g1m_make_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *rawhead) +{ + /* allocate the handle */ + *handle = malloc(sizeof(g1m_mcsfile_t)); + if (!handle) return (g1m_error_alloc); + g1m_mcsfile_t *h = *handle; + memset(h, 0, sizeof(g1m_mcsfile_t)); + + /* copy the head */ + memcpy(&h->head, rawhead, sizeof(g1m_mcshead_t)); + g1m_mcshead_t *head = &h->head; + + /* act differently according to the context */ + switch (head->type) { + case g1m_mcstype_list: case g1m_mcstype_mat: case g1m_mcstype_vct: + case g1m_mcstype_ssheet: + log_info("Preparing %d*%d matrix", head->width, head->height); + unsigned int wd = head->width, ht = head->height; + if (wd && ht) { + h->cells = malloc(sizeof(g1m_mcs_cell_t*) * ht); + if (!h->cells) goto fail; + 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++) + h->cells[y] = &h->cells[0][h->head.width * y]; + } + break; + + case g1m_mcstype_var: + if (head->count <= 1) h->vars = &h->var; + else { + h->vars = malloc(sizeof(g1m_mcs_cell_t) * head->count); + if (!h->vars) goto fail; + memset(h->vars, 0, sizeof(g1m_mcs_cell_t) * head->count); + } + break; + + case g1m_mcstype_pict: case g1m_mcstype_capt: + /* set count */ + head->count = (head->type == g1m_mcstype_pict) ? 2 : 1; + + /* allocate directory */ + if (head->count <= 1) h->pics = &h->pic; + else { + h->pics = malloc(sizeof(uint32_t**) * head->count); + if (!h->pics) goto fail; + } + + /* allocate */ + for (int i = 0; i < head->count; i++) { + h->pics[i] = alloc_pixels(head->width, head->height); + if (!h->pics[i]) { + for (int j = 0; j < i; j++) + free(h->pics[j]); + if (h->pics != &h->pic) + free(h->pics); + goto fail; + } + } + + /* prepare */ + for (int i = 0; i < head->count; i++) + prepare_pixels(h->pics[i], head->width, head->height) + break; + + case g1m_mcstype_end: + break; + + /* those are TEMPORARY XXX */ + case g1m_mcstype_setup: case g1m_mcstype_string: + break; + + default: + h->content = malloc(head->size); + if (!h->content) goto fail; + break; + } + + /* finish */ + return (0); +fail: + free(h); + *handle = NULL; + return (g1m_error_alloc); +} + /* ************************************************************************** */ /* Internal functions */ /* ************************************************************************** */ @@ -27,18 +129,16 @@ * Find space for some element function. * * @arg handle the handle. - * @arg type the type. - * @arg name the name. - * @arg id the ID. + * @arg head the head. * @return the mcs file (NULL if allocation error). */ -static g1m_mcsfile_t *find_space_for_file(g1m_t *handle, - unsigned int type, char *name, int id) +static g1m_mcsfile_t *find_space_for_file(g1m_t *handle, g1m_mcshead_t *head) { g1m_mcsfile_t **pfile = NULL; /* look if this file isn't already in the tab */ + int istyp = g1m_mcshead_uses_id(head); for (int i = 0; i < handle->count; i++) { g1m_mcsfile_t *file = handle->files[i]; if (!file) { @@ -46,9 +146,9 @@ static g1m_mcsfile_t *find_space_for_file(g1m_t *handle, continue; } - if ((file->head.type & type) - && (id ? file->head.id == id : !strcmp(file->head.name, name))) { - g1m_free_mcsfile_content(file); + if ((file->head.type == head->type) && (istyp ? + file->head.id == head->id : !strcmp(file->head.name, head->name))) { + g1m_free_mcsfile(file); pfile = &handle->files[i]; goto found; } @@ -65,25 +165,17 @@ static g1m_mcsfile_t *find_space_for_file(g1m_t *handle, pfile = &handle->files[handle->count++]; } - /* allocate the file */ - if (!(*pfile = malloc(sizeof(g1m_mcsfile_t)))) return (NULL); - found:; - /* don't forget to copy basic things */ - g1m_mcsfile_t *file = *pfile; - if (name) sprintf(file->head.name, "%.8s", name); - file->head.type = type; - file->head.id = id; - - /* and use mcstype utilities to copy other info */ - g1m_correct_mcsfile_head(&file->head); + /* make the file */ + int err = g1m_make_mcsfile(pfile, head); + if (err) return (NULL); /* return it */ - return (file); + return (*pfile); } /* ************************************************************************** */ -/* Public functions */ +/* Create files in archive */ /* ************************************************************************** */ /** * g1m_putmcs_program: @@ -103,19 +195,19 @@ int g1m_putmcs_program(g1m_t *handle, g1m_mcsfile_t **pfile, if (~handle->type & g1m_type_mcs) return (g1m_error_op); /* find the file */ - g1m_mcsfile_t *file = - find_space_for_file(handle, g1m_mcstype_program, name, 0); + g1m_mcshead_t head = { + .type = g1m_mcstype_program, + .size = strlen(content) + }; + strncpy(head.name, name, 8); head.name[8] = 0; + if (password) strncpy(head.password, password, 8); + else head.password[0] = 0; + g1m_mcsfile_t *file = find_space_for_file(handle, &head); if (!file) return (g1m_error_alloc); /* set content */ - file->head.size = strlen(content); - if (!(file->content = malloc(file->head.size))) return (g1m_error_alloc); memcpy(file->content, content, file->head.size); - /* set password */ - if (password) strncpy(file->password, password, 8); - else g1m_remove_password(file); - /* no error */ if (pfile) *pfile = file; return (0); @@ -142,22 +234,15 @@ int g1m_putmcs_capture(g1m_t *handle, g1m_mcsfile_t **pfile, return (g1m_error_op); /* find the file */ - g1m_mcsfile_t *file = - find_space_for_file(handle, g1m_mcstype_capture, NULL, id); + g1m_mcshead_t head = { + .type = g1m_mcstype_capture, .id = id, + .width = width, .height = height + }; + g1m_mcsfile_t *file = find_space_for_file(handle, &head); if (!file) return (g1m_error_alloc); - /* prepare picture */ - file->width = width; - file->height = height; - file->image = NULL; - - /* allocate */ - file->image = alloc_pixels(width, height); - if (!file->image) return (g1m_error_alloc); - prepare_pixels(file->image, width, height); - /* copy pixels */ - uint32_t *pix = &file->image[0][0]; + uint32_t *pix = &file->pic[0][0]; for (int y = 0; y < height; y++) { uint32_t *line = *pic++; for (int x = 0; x < width; x++) @@ -189,32 +274,16 @@ int g1m_putmcs_picture(g1m_t *handle, g1m_mcsfile_t **pfile, return (g1m_error_op); /* find the file */ - g1m_mcsfile_t *file = - find_space_for_file(handle, g1m_mcstype_picture, NULL, id); + g1m_mcshead_t head = { + .type = g1m_mcstype_picture, .id = id, + .width = 128, .height = 64 + }; + g1m_mcsfile_t *file = find_space_for_file(handle, &head); if (!file) return (g1m_error_alloc); - /* prepare pictures */ - file->width = 128; - file->height = 64; - file->image = NULL; - file->second_image = NULL; - - /* allocate */ - file->image = alloc_pixels(128, 64); - if (!file->image) return (g1m_error_alloc); - file->second_image = alloc_pixels(128, 64); - if (!file->second_image) { - free(file->image); file->image = NULL; - return (g1m_error_alloc); - } - - /* prepare */ - prepare_pixels(file->image, 128, 64) - prepare_pixels(file->second_image, 128, 64) - /* copy pixels */ - uint32_t *one = &file->image[0][0]; - uint32_t *two = &file->second_image[0][0]; + uint32_t *one = &file->pics[0][0][0]; + uint32_t *two = &file->pics[1][0][0]; for (int y = 0; y < 64; y++) { uint32_t *line_one = *pic_one++; uint32_t *line_two = *pic_two++; diff --git a/src/type/cas.c b/src/type/cas.c index f674944..ad927d6 100644 --- a/src/type/cas.c +++ b/src/type/cas.c @@ -75,13 +75,19 @@ static struct type_corresp cas_groups[] = { * g1m_maketype_cas: * Get the libg1m MCS type from raw CAS identification data. * + * @arg head the head to fill. * @arg datatype the data type string. - * @arg type[out] the libg1m MCS type. * @return the error (if any). */ -int g1m_maketype_cas(const char *datatype, g1m_mcstype_t *type) +int g1m_maketype_cas(g1m_mcshead_t *head, const char *datatype) { + /* copy information */ + head->flags |= g1m_mcsinfo_cas; + memcpy(head->_datatype, datatype, 2); + head->_datatype[2] = 0; + + /* look for correspondance */ struct type_corresp *c = cas_groups - 1; while ((++c)->datatype) { if (c->datatype && strncmp(datatype, c->datatype, 4)) @@ -91,12 +97,12 @@ int g1m_maketype_cas(const char *datatype, g1m_mcstype_t *type) if (!c->type) goto notfound; /* fill in info and return */ - if (type) *type = c->type; + head->type = c->type; return (0); notfound: log_info("Type with '%.4s' data string was not implemented or not " "recognized.", datatype); - if (type) *type = 0; + head->type = 0; return (1); } diff --git a/src/type/caspro.c b/src/type/caspro.c index 43dceda..bbf0117 100644 --- a/src/type/caspro.c +++ b/src/type/caspro.c @@ -54,29 +54,38 @@ static struct type_corresp cas_types[] = { * g1m_maketype_caspro: * Get the libg1m MCS type from raw CAS identification data. * + * @arg head the head to fill. + * @arg maintype the main type string. * @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) +int g1m_maketype_caspro(g1m_mcshead_t *head, + const char *maintype, const char *datatype) { + /* copy raw information */ + head->flags |= g1m_mcsinfo_caspro; + memcpy(head->_maintype, maintype, 3); + head->_maintype[3] = 0; + memcpy(head->_datatype, datatype, 2); + head->_datatype[2] = 0; + + /* look for correspondance */ 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? */ + if ((!c->maintype || !strncmp(maintype, c->maintype, 3)) + && (!c->datatype || !strncmp(datatype, c->datatype, 2))) break; } if (!c->maintype) goto notfound; /* fill in info and return */ - if (type) *type = c->type; + head->type = c->type; return (0); notfound: log_info("Type with '%.4s' data string was not implemented or not " "recognized.", datatype); - if (type) *type = 0; + head->type = 0; return (1); } diff --git a/src/type/mcs.c b/src/type/mcs.c index be132fd..e796f29 100644 --- a/src/type/mcs.c +++ b/src/type/mcs.c @@ -228,21 +228,35 @@ static int get_number(const char *s, int *num, int isnum) * g1m_maketype_mcs: * Get libg1m type from rawtype. * - * @arg gname the MCS group name. + * @arg head the head to fill. + * @arg gname the group name. + * @arg dname the directory name. * @arg fname the filename. - * @arg rawtype the raw number type. - * @arg type pointer to the real type field to fill. - * @arg id pointer to the ID to fill. + * @arg rawtype the raw numerical type. * @return if the type was not found (0 if yes). */ -int g1m_maketype_mcs(const char *gname, const char *fname, - unsigned int rawtype, g1m_mcstype_t *type, int *id) +int g1m_maketype_mcs(g1m_mcshead_t *head, + const char *gname, const char *dname, + const char *fname, unsigned int rawtype) { /* log what we're looking for */ log_info("Looking for type with '%.8s' group, '%.8s' name and " "0x%02X raw type", gname, fname, rawtype); + /* copy raw information */ + head->flags |= g1m_mcsinfo_mcs; + memcpy(head->name, fname, 8); + head->name[8] = 0; + memcpy(head->_group, gname, 16); + head->_group[16] = 0; + head->_rawtype = rawtype; + if (dname) { + memcpy(head->_dirname, dname, 8); + head->_dirname[8] = 0; + } else + memset(head->_dirname, 0, 9); + /* look for group correspondance */ int gid = 0; struct group_corresp *g = mcs_groups - 1; @@ -284,15 +298,15 @@ int g1m_maketype_mcs(const char *gname, const char *fname, goto notfound; /* fill in info and return */ - if (type) *type = t->type; - if (id) *id = fid; + head->type = t->type; + head->id = fid; return (0); notfound: log_info("Type with '%s' group, '%s' name and 0x%02x type " "wasn't recognized.", gname, fname, rawtype); - if (type) *type = 0; - if (id) *id = 0; + head->type = 0; + head->id = 0; return (1); } diff --git a/src/utils/skip.c b/src/utils/skip.c index cad2d06..620c652 100644 --- a/src/utils/skip.c +++ b/src/utils/skip.c @@ -37,6 +37,7 @@ int g1m_skip(g1m_buffer_t *buffer, size_t size, uint_fast32_t *checksum) /* read that much */ size_t curlen = min(size, 1024); size -= curlen; + buffer->_offset += curlen; if ((err = (*buffer->read)(buffer->cookie, buf, curlen))) { log_error("Skipping has failed after %" PRIuSIZE " bytes", orig - size);