diff --git a/include/libg1m.h b/include/libg1m.h index e700665..4cc310b 100644 --- a/include/libg1m.h +++ b/include/libg1m.h @@ -73,42 +73,46 @@ typedef int g1m_error_t; extern const char *g1m_error_strings[]; # define g1m_strerror(N) g1m_error_strings[N] # define g1m_geterror(N) g1m_error_strings[N] - /* ************************************************************************** */ /* Main functions */ /* ************************************************************************** */ /* open and free a handle */ -int g1m_decode(g1m_t *handle, const char *path, g1m_buffer_t *buffer, - g1m_type_t expected_type); -void g1m_free(g1m_t *handle); +extern int g1m_decode(g1m_t *handle, const char *path, g1m_buffer_t *buffer, + g1m_type_t allowed_types); +extern void g1m_free(g1m_t *handle); /* open a handle using FILEs */ #ifndef G1M_DISABLED_FILE -int g1m_open(g1m_t **handle, const char *path, - g1m_type_t expected_type); -int g1m_fopen(g1m_t **handle, const char *path, FILE *stream, - g1m_type_t expected_type); +extern int g1m_open(g1m_t **handle, const char *path, + g1m_type_t allowed_types); +extern int g1m_fopen(g1m_t **handle, const char *path, FILE *stream, + g1m_type_t allowed_types); #endif +/* Make a handle */ +extern int g1m_make_mcs(g1m_t **h, int count); +extern int g1m_make_picture(g1m_t **h, unsigned int width, unsigned int height); /* ************************************************************************** */ /* Main MCS functions */ /* ************************************************************************** */ /* make an MCS file out of a head */ -int g1m_make_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *rawhead); -int g1m_prepare_mcsfile_heads(g1m_mcshead_t *head, g1m_mcshead_t *heads); -void g1m_free_mcsfile(g1m_mcsfile_t *handle); +extern int g1m_make_mcsfile(g1m_mcsfile_t **handle, + const g1m_mcshead_t *rawhead); +extern int g1m_prepare_mcsfile_heads(g1m_mcshead_t *head, + g1m_mcshead_t *heads); +extern void g1m_free_mcsfile(g1m_mcsfile_t *handle); /* open MCS head for decoding, correct it for encoding */ -int g1m_decode_mcsfile_head(g1m_mcshead_t *head, +extern 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_correct_mcsfile_head(g1m_mcshead_t *head); /* open and decode MCS file */ -int g1m_decode_mcsfile(g1m_mcsfile_t **handle, +extern int g1m_decode_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *head, g1m_buffer_t *buffer); -int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle, +extern int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle, const g1m_mcshead_t *head, const unsigned char *data, size_t size); /* open CAS head for decoding @@ -118,20 +122,19 @@ int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle, * `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_casfiles_part(g1m_mcshead_t *head, g1m_mcshead_t *heads, +extern int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer); +extern int g1m_decode_casfiles_part(g1m_mcshead_t *head, g1m_mcshead_t *heads, g1m_buffer_t *buffer); -int g1m_decode_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer); - +extern int g1m_decode_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer); /* ************************************************************************** */ /* MCS archive management */ /* ************************************************************************** */ /* add MCS files */ -int g1m_putmcs_program(g1m_t *handle, g1m_mcsfile_t **pfile, +extern int g1m_putmcs_program(g1m_t *handle, g1m_mcsfile_t **pfile, char *name, char *password, char *content); -int g1m_putmcs_capture(g1m_t *handle, g1m_mcsfile_t **pfile, +extern int g1m_putmcs_capture(g1m_t *handle, g1m_mcsfile_t **pfile, int id, int width, int height, uint32_t **pixels); -int g1m_putmcs_picture(g1m_t *handle, g1m_mcsfile_t **pfile, +extern int g1m_putmcs_picture(g1m_t *handle, g1m_mcsfile_t **pfile, int id, uint32_t **pixels_one, uint32_t **pixels_two); # ifdef __cplusplus diff --git a/include/libg1m/eact.h b/include/libg1m/eact.h index 7904d4e..8c108d2 100644 --- a/include/libg1m/eact.h +++ b/include/libg1m/eact.h @@ -33,7 +33,6 @@ typedef unsigned int g1m_eact_line_type_t; # define g1m_linetype_pict g1m_linetype_picture # define g1m_linetype_heading g1m_linetype_title # define g1m_linetype_standard_heading g1m_linetype_title - /* ************************************************************************** */ /* E-activities line structure */ /* ************************************************************************** */ diff --git a/include/libg1m/file.h b/include/libg1m/file.h index 39d2dfb..5e6c484 100644 --- a/include/libg1m/file.h +++ b/include/libg1m/file.h @@ -22,8 +22,7 @@ /* This header defines the way storage files are stored here. * * TODO: - * What I think I should do is trees and folders in two different lists. - */ + * What I think I should do is trees and folders in two different lists. */ /* ************************************************************************** */ /* Storage file types */ /* ************************************************************************** */ diff --git a/include/libg1m/format.h b/include/libg1m/format.h index edbcb09..ef70ade 100644 --- a/include/libg1m/format.h +++ b/include/libg1m/format.h @@ -29,7 +29,7 @@ /* ************************************************************************** */ /* 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. + * the fx-9860G (Graph 85) was announced, around 2004/2005. * 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. * @@ -79,9 +79,9 @@ /* ************************************************************************** */ /* The G1M/STD format */ /* ************************************************************************** */ -/* Since around 2004, CASIO has adopted a single "superformat"; we call it +/* Since around 2004/2005, CASIO has adopted a single "superformat"; we call it * CASIO's standard format, or the G1M format (it doesn't really have a - * *public* name, other than its magics, like USBPower or CASIO). + * *public* name, other than its magics, like 'USBPower' or 'CASIO'). * * It doesn't have a single magic string, but a few. But the standard header * has the same format, so we consider it as the same format. */ diff --git a/include/libg1m/formatutils.h b/include/libg1m/formatutils.h index 48b0b14..5d17941 100644 --- a/include/libg1m/formatutils.h +++ b/include/libg1m/formatutils.h @@ -27,11 +27,15 @@ #ifndef LIBG1M_FORMATUTILS_H # define LIBG1M_FORMATUTILS_H # include +# ifdef __cplusplus +extern "C" { +# endif /* ************************************************************************** */ /* General types (`g1m_t`) */ /* ************************************************************************** */ -int g1m_maketype_std(const char *path, +/* Standard header */ +extern 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); @@ -40,16 +44,19 @@ int g1m_maketype_std(const char *path, /* MCS types (`g1m_mcshead_t`/`g1m_mcsfile_t`) */ /* ************************************************************************** */ /* get mcs type data */ -int g1m_maketype_mcs(g1m_mcshead_t *head, +extern 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(g1m_mcshead_t *head, +extern int g1m_maketype_cas(g1m_mcshead_t *head, const char *datatype); /* get caspro type data */ -int g1m_maketype_caspro(g1m_mcshead_t *head, +extern int g1m_maketype_caspro(g1m_mcshead_t *head, const char *maintype, const char *datatype); +# ifdef __cplusplus +} +# endif #endif /* LIBG1M_FORMATUTILS_H */ diff --git a/include/libg1m/handle.h b/include/libg1m/handle.h index c856d8d..c7094b5 100644 --- a/include/libg1m/handle.h +++ b/include/libg1m/handle.h @@ -54,7 +54,6 @@ typedef unsigned int g1m_platform_t; /* Platform macros */ # define g1m_platform(P) ((P) & 0x7FFF) - /* ************************************************************************** */ /* Helpers */ /* ************************************************************************** */ @@ -64,7 +63,6 @@ typedef struct g1m_version_s { int minor; int revision; } g1m_version_t; - /* ************************************************************************** */ /* Handle structure */ /* ************************************************************************** */ diff --git a/include/libg1m/internals.h b/include/libg1m/internals.h index e7702bf..a0d3988 100644 --- a/include/libg1m/internals.h +++ b/include/libg1m/internals.h @@ -170,9 +170,6 @@ G1M_CASFUNC(matrix) /* ************************************************************************** */ /* Utilities */ /* ************************************************************************** */ -/* Making */ -int g1m_make_mcs(g1m_t **h); - /* Free-ing */ void g1m_free_content(g1m_t *handle); void g1m_free_mcs(g1m_t *handle); diff --git a/include/libg1m/internals/log.h b/include/libg1m/internals/log.h index 7361eb6..a9ec971 100644 --- a/include/libg1m/internals/log.h +++ b/include/libg1m/internals/log.h @@ -77,10 +77,12 @@ # define log_fatal(S, ...) # endif -/* Functions prototypes */ -void g1m_log_mem(const char *prefix, void *m, size_t n); -const char *g1m_get_type_string(int main_id, int type); -const char *g1m_get_mcs_ftype_string(int code); -const char *g1m_get_eact_ltype_string(int code); +/* Log memory (behind the `logm_*` macros) */ +extern void g1m_log_mem(const char *prefix, void *m, size_t n); + +/* Type strings */ +extern const char *g1m_get_type_string(int main_id, int type); +extern const char *g1m_get_mcs_ftype_string(int code); +extern const char *g1m_get_eact_ltype_string(int code); #endif /* LIBG1M_INTERNALS_LOG_H */ diff --git a/include/libg1m/picture.h b/include/libg1m/picture.h index e124d16..06db78c 100644 --- a/include/libg1m/picture.h +++ b/include/libg1m/picture.h @@ -18,6 +18,9 @@ * ************************************************************************** */ #ifndef LIBG1M_PICTURE_H # define LIBG1M_PICTURE_H +# ifdef __cplusplus +extern "C" { +# endif /* picture format */ typedef int g1m_pictureformat_t; @@ -26,26 +29,42 @@ typedef int g1m_pictureformat_t; # define g1m_pictureformat_2bit_dual 0x0201 # define g1m_pictureformat_4bit_rgb 0x0401 # define g1m_pictureformat_4bit_code 0x0402 +# define g1m_pictureformat_4bit_color 0x0403 +# define g1m_pictureformat_4bit_mono 0x0404 # define g1m_pictureformat_16bit 0x1000 /* get size of the raw buffer */ # define g1m_picturesize_1bit_packed(W, H) \ ((W) * (H) / 8) +# define g1m_picturesize_1bit_reverse(W, H) \ + g1m_picturesize_1bit_packed(W, H) +# define g1m_picturesize_1bit_color(W, H) \ + (4 * g1m_picturesize_1bit_reverse(W, H)) +# define g1m_picturesize_1bit_mono(W, H) \ + g1m_picturesize_1bit_color(W, H) + # define g1m_picturesize_2bit_dual(W, H) \ (((W) * (H) / 4) * 2) # define g1m_picturesize_4bit(W, H) \ ((W) * (H) / 2) + # define g1m_picturesize_4bit_rgb(W, H) \ g1m_picturesize_4bit(W, H) # define g1m_picturesize_4bit_code(W, H) \ g1m_picturesize_4bit(W, H) + # define g1m_picturesize_16bit(W, H) \ ((W) * (H) * 2) /* encoding and decoding functions */ -int g1m_decode_picture(uint32_t **pixels, g1m_pictureformat_t format, - const unsigned char *raw, unsigned int width, unsigned int height); -int g1m_encode_picture(const uint32_t **pixels, g1m_pictureformat_t format, - unsigned char *raw, unsigned int width, unsigned int height); +extern int g1m_decode_picture(uint32_t **pixels, + g1m_pictureformat_t format, const unsigned char *raw, + unsigned int width, unsigned int height); +extern int g1m_encode_picture(const uint32_t **pixels, + g1m_pictureformat_t format, unsigned char *raw, + unsigned int width, unsigned int height); +# ifdef __cplusplus +} +# endif #endif /* LIBG1M_PICTURE_H */ diff --git a/src/core/free.c b/src/core/free.c index 66d605c..65b6310 100644 --- a/src/core/free.c +++ b/src/core/free.c @@ -40,82 +40,3 @@ void g1m_free_line_content(g1m_line_t *line) free(line->lines); } } - -/** - * g1m_free_mcs: - * Free all of the MCS. - * - * @arg handle the handle to close. - */ - -void g1m_free_mcs(g1m_t *handle) -{ - /* check if mcs */ - if (!handle->files) - return ; - - /* foreach file in mcs */ - g1m_mcsfile_t **files = handle->files; - int file_count = handle->count; - for (int i = 0; i < file_count; i++) { - /* free the file if exists */ - if (files[i]) g1m_free_mcsfile(files[i]); - } - free(handle->files); handle->files = NULL; -} - -/** - * g1m_free_content: - * Free handle data. - * - * @arg handle the handle to close. - */ - -void g1m_free_content(g1m_t *handle) -{ - /* addin time! */ - if (handle->type & g1m_type_addin) - free(handle->pixels); - - /* mcs time! */ - if (handle->type & g1m_type_mcs) - g1m_free_mcs(handle); - - /* messages time! */ - if (handle->type & g1m_type_lang - && handle->messages) { - for (int i = 0; i < handle->count; i++) - free(handle->messages[i]); - free(handle->messages); - } - - /* function keys time! */ - if (handle->type & g1m_type_fkey - && handle->fkeys) { - for (int i = 0; i < handle->count; i++) - free(handle->fkeys[i]); - free(handle->fkeys); - } - - /* picture time! */ - if (handle->type & g1m_type_picture) - free(handle->pixels); - - /* e-activities time! */ - if (handle->type & g1m_type_eact) - g1m_free_line_content(handle->line); -} - -/** - * g1m_free: - * Free a handle and its data. - * - * @arg handle the handle. - */ - -void g1m_free(g1m_t *handle) -{ - if (!handle) return ; - g1m_free_content(handle); - free(handle); -} diff --git a/src/decode/main.c b/src/decode/main.c index fe1e74d..cd68f64 100644 --- a/src/decode/main.c +++ b/src/decode/main.c @@ -41,6 +41,7 @@ static struct corresp correspondances[] = { // {"g1s", g1m_type_storage, g1m_decode_storage}, {"grc", g1m_type_mcs, g1m_decode_grc}, + /* terminating entry */ {NULL, 0, NULL} }; diff --git a/src/decode/mcs/picture.c b/src/decode/mcs/picture.c index 98c1c18..83d4bb3 100644 --- a/src/decode/mcs/picture.c +++ b/src/decode/mcs/picture.c @@ -18,52 +18,6 @@ * ************************************************************************** */ #include -/* ************************************************************************** */ -/* Internal functions */ -/* ************************************************************************** */ -/** - * get_image: - * Allocate space, and convert monochromic image to 0x0RGB. - * - * @arg buffer the buffer to read from. - * @arg img the image to make. - * @arg width the image width. - * @arg height the image height. - */ - -static int get_image(g1m_buffer_t *buffer, uint32_t **image, - unsigned int width, unsigned int height) -{ - /* get raw pixels */ - size_t linesize = width / 8 + !!(width % 8); - size_t bufsize = height * linesize; - uint8_t buf[bufsize]; - READ(buf, bufsize) - - /* fill */ - for (uint_fast16_t y = 0; y < height; y++) { - /* init vars for monochrome with fill bits image browsing */ - uint8_t *b = &buf[y * linesize]; - int bit = 1 << 7; - - /* browse and save pixels! (monochrome to 0x0RGB) */ - for (uint_fast16_t x = 0; x < width; x++) { - /* set pixel */ - image[y][x] = *b & bit ? 0xffffff : 0x000000; - - /* go further */ - b += bit & 1; - bit = (bit >> 1) | ((bit & 1) << 7); - } - } - - /* no error */ - return (0); -} - -/* ************************************************************************** */ -/* Real decode functions */ -/* ************************************************************************** */ /** * g1m_decode_mcs_capture: * Decode a capture. @@ -87,15 +41,25 @@ int g1m_decode_mcs_capture(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, head->height = hd.height; int err = g1m_make_mcsfile(handle, head); if (err) return (err); + g1m_mcsfile_t *h = *handle; /* print info */ - g1m_mcsfile_t *h = *handle; log_info("capture is %dx%d sized", h->head.width, h->head.height); + /* read raw data */ + size_t pic_size = g1m_picturesize_1bit_packed(head->width, head->height); + uint8_t pic_raw[pic_size]; READ(pic_raw, pic_size) + /* get the image and return */ - err = get_image(buffer, h->pics[0], h->head.width, h->head.height); - if (err) { g1m_free_mcsfile(*handle); free(*handle); } - return (err); + if ((err = g1m_decode_picture(h->pics[0], g1m_pictureformat_1bit_packed, + pic_raw, head->width, head->height))) { + g1m_free_mcsfile(*handle); + *handle = NULL; + return (err); + } + + /* no error! */ + return (0); } /** @@ -116,24 +80,22 @@ int g1m_decode_mcs_picture(g1m_mcsfile_t **handle, g1m_buffer_t *buffer, head->height = 64; int err = g1m_make_mcsfile(handle, head); if (err) return (err); - - /* get the first image */ g1m_mcsfile_t *h = *handle; - if ((err = get_image(buffer, h->pics[0], 128, 64))) { - log_fatal("Failed to get the first image."); - goto fail; - } - /* and the second */ - if ((err = get_image(buffer, h->pics[1], 128, 64))) { - log_fatal("Failed to get the second image."); - goto fail; + /* get the images */ + size_t pic_size = g1m_picturesize_1bit_packed(head->width, head->height); + uint8_t pics_raw[pic_size * 2]; READ(pics_raw, pic_size * 2) + + /* decode the images */ + if ((err = g1m_decode_picture(h->pics[0], g1m_pictureformat_1bit_packed, + pics_raw, head->width, head->height)) + || (err = g1m_decode_picture(h->pics[1], g1m_pictureformat_1bit_packed, + &pics_raw[pic_size], head->width, head->height))) { + g1m_free_mcsfile(*handle); + *handle = NULL; + return (err); } /* no error */ return (0); -fail: - g1m_free_mcsfile(*handle); - *handle = NULL; - return (err); } diff --git a/src/manage/create.c b/src/manage/create.c deleted file mode 100644 index b673c3c..0000000 --- a/src/manage/create.c +++ /dev/null @@ -1,45 +0,0 @@ -/* ***************************************************************************** - * manage/create.c -- create a handle. - * 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 - -/** - * g1m_make_mcs: - * Make an MCS file. - * - * @arg h pointer to the handle to create. - * @return the error code (0 if ok). - */ - -int g1m_make_mcs(g1m_t **h) -{ - /* allocate the handle */ - *h = malloc(sizeof(g1m_t)); - if (!*h) return (g1m_error_alloc); - - /* initialize it */ - g1m_t *handle = *h; - handle->type = g1m_type_mcs; - handle->platform = g1m_platform_fx; - handle->count = 0; - handle->_size = 0; - handle->files = NULL; - - /* no error */ - return (0); -} diff --git a/src/manage/handle.c b/src/manage/handle.c new file mode 100644 index 0000000..8ac24ef --- /dev/null +++ b/src/manage/handle.c @@ -0,0 +1,165 @@ +/* ***************************************************************************** + * manage/handle.c -- create, free a handle. + * 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 + +/* ************************************************************************** */ +/* Make a handle */ +/* ************************************************************************** */ +/** + * g1m_make_picture: + * Make a picture handle. + * + * @arg handle the handle to make. + * @arg width the picture width. + * @arg height the picture height. + * @return the error code (0 if ok). + */ + +int g1m_make_picture(g1m_t **h, unsigned int width, unsigned int height) +{ + /* allocate the handle */ + *h = malloc(sizeof(g1m_t)); + if (!*h) return (g1m_error_alloc); + g1m_t *handle = *h; + + /* allocate the pixels */ + handle->width = width; + handle->height = height; + handle->pixels = alloc_pixels(width, height); + if (!handle->pixels) { free(*h); *h = NULL; return (g1m_error_alloc); } + prepare_pixels(handle->pixels, width, height) + + /* everything went well! */ + return (0); +} + +/** + * g1m_make_mcs: + * Make an MCS file. + * + * @arg h pointer to the handle to create. + * @arg count the number of slots in the index. + * @return the error code (0 if ok). + */ + +int g1m_make_mcs(g1m_t **h, int count) +{ + /* allocate the handle */ + *h = malloc(sizeof(g1m_t)); + if (!*h) return (g1m_error_alloc); + + /* initialize it */ + g1m_t *handle = *h; + handle->type = g1m_type_mcs; + handle->platform = g1m_platform_fx; + + /* allocate space */ + handle->count = count; handle->_size = count; + handle->files = NULL; + if (count) { + handle->files = malloc(sizeof(g1m_mcsfile_t*) * count); + if (!handle->files) { free(*h); *h = NULL; return (g1m_error_alloc); } + memset(handle->files, 0, sizeof(g1m_mcsfile_t*) * count); + } + + /* no error */ + return (0); +} + +/* ************************************************************************** */ +/* Free a handle */ +/* ************************************************************************** */ +/** + * g1m_free_mcs: + * Free all of the MCS. + * + * @arg handle the handle to close. + */ + +void g1m_free_mcs(g1m_t *handle) +{ + /* check if mcs */ + if (!handle->files) + return ; + + /* foreach file in mcs */ + g1m_mcsfile_t **files = handle->files; + int file_count = handle->count; + for (int i = 0; i < file_count; i++) { + /* free the file if exists */ + if (files[i]) g1m_free_mcsfile(files[i]); + } + free(handle->files); handle->files = NULL; +} + +/** + * g1m_free_content: + * Free handle data. + * + * @arg handle the handle to close. + */ + +void g1m_free_content(g1m_t *handle) +{ + /* addin time! */ + if (handle->type & g1m_type_addin) + free(handle->pixels); + + /* mcs time! */ + if (handle->type & g1m_type_mcs) + g1m_free_mcs(handle); + + /* messages time! */ + if (handle->type & g1m_type_lang + && handle->messages) { + for (int i = 0; i < handle->count; i++) + free(handle->messages[i]); + free(handle->messages); + } + + /* function keys time! */ + if (handle->type & g1m_type_fkey + && handle->fkeys) { + for (int i = 0; i < handle->count; i++) + free(handle->fkeys[i]); + free(handle->fkeys); + } + + /* picture time! */ + if (handle->type & g1m_type_picture) + free(handle->pixels); + + /* e-activities time! */ + if (handle->type & g1m_type_eact) + g1m_free_line_content(handle->line); +} + +/** + * g1m_free: + * Free a handle and its data. + * + * @arg handle the handle. + */ + +void g1m_free(g1m_t *handle) +{ + if (!handle) return ; + g1m_free_content(handle); + free(handle); +} diff --git a/src/type/cas.c b/src/type/cas.c index ac27f1d..87f6639 100644 --- a/src/type/cas.c +++ b/src/type/cas.c @@ -55,7 +55,8 @@ static struct type_corresp cas_groups[] = { {"AM", 0, 0}, // alpha variable memory {"BU", 0, 0}, // backup {"DM", 0, 0}, // defined memory - {"DD", 0, 0}, // screenshot + {"DC", 0, 0}, // color screenshot + {"DD", 0, 0}, // monochrome screenshot {"EN", 0, 0}, // one editor file {"FN", 0, 0}, // set of editor files {"FT", 0, 0}, // ??? (cafix) diff --git a/src/type/caspro.c b/src/type/caspro.c index dc99858..182b2de 100644 --- a/src/type/caspro.c +++ b/src/type/caspro.c @@ -44,6 +44,7 @@ struct app_corresp { static struct app_corresp apps[] = { {"TXT", 0, 0}, /* editor */ {"VAL", 0, 0}, /* RUN? */ + {"IMG", 0, 0}, /* picture */ {"REQ", flg_flags, g1m_mcsflag_request}, /* request */ {"END", flg_type, g1m_mcstype_end}, /* end */ diff --git a/src/utils/picture.c b/src/utils/picture.c index e6f0028..3086692 100644 --- a/src/utils/picture.c +++ b/src/utils/picture.c @@ -55,9 +55,11 @@ static const uint32_t prizm_colors[16] = { int g1m_decode_picture(uint32_t **pixels, g1m_pictureformat_t format, const unsigned char *raw, unsigned int width, unsigned int height) { - int msk; + int msk; const unsigned char *o, *g, *b, *r2; size_t off; switch (format) { + case g1m_pictureformat_4bit_mono: + raw = &raw[(height * width / 2) * 2]; case g1m_pictureformat_1bit_packed: msk = 0x80; for (unsigned int y = 0; y < height; y++) @@ -72,10 +74,9 @@ int g1m_decode_picture(uint32_t **pixels, g1m_pictureformat_t format, break; case g1m_pictureformat_1bit_reverse: - msk = 0x80; for (unsigned int bx = width - 8; bx != (unsigned int)-8; bx -= 8) for (unsigned int y = height - 1; y != (unsigned int)-1; y--) { - msk = 0x00; + msk = 0x80; for (unsigned int x = bx; x < bx + 8; x++) { /* get pixel */ pixels[y][x] = (*raw & msk) ? 0x000000 : 0xFFFFFF; @@ -90,7 +91,7 @@ int g1m_decode_picture(uint32_t **pixels, g1m_pictureformat_t format, break; case g1m_pictureformat_2bit_dual: - msk = 0x80; const unsigned char *r2 = &raw[height * width / 8]; + msk = 0x80; r2 = &raw[height * width / 8]; for (unsigned int y = 0; y < height; y++) for (unsigned int x = 0; x < width; x++) { /* get pixel */ @@ -135,14 +136,35 @@ int g1m_decode_picture(uint32_t **pixels, g1m_pictureformat_t format, } break; + case g1m_pictureformat_4bit_color:; + off = height * width / 8; o = raw; g = &raw[off]; b = &raw[off * 2]; + for (unsigned int bx = width - 8; bx != (unsigned int)-8; bx -= 8) + for (unsigned int y = height - 1; y != (unsigned int)-1; y--) { + msk = 0x80; + for (unsigned int x = bx; x < bx + 8; x++) { + /* get pixel */ + if (*o & msk) pixels[y][x] = 0xFF8C00; /* orange */ + else if (*g & msk) pixels[y][x] = 0x00FF00; /* green */ + else if (*b & msk) pixels[y][x] = 0x0000FF; /* blue */ + else pixels[y][x] = 0xFFFFFF; /* white */ + + /* go to next */ + msk >>= 1; + } + + /* go to next byte */ + o++; g++; b++; + } + break; + case g1m_pictureformat_16bit: for (unsigned int y = 0; y < height; y++) for (unsigned int x = 0; x < width; x++) { /* get pixel */ - uint32_t o = raw[0], t = raw[1]; - uint32_t px = (o >> 3) << (16 + 3); - px |= (((o & 7) << 3) | (t >> 5)) << (8 + 2); - px |= (t & 31) << 3; + uint32_t one = raw[0], two = raw[1]; + uint32_t px = (one >> 3) << (16 + 3); + px |= (((one & 7) << 3) | (two >> 5)) << (8 + 2); + px |= (two & 31) << 3; pixels[y][x] = px; /* go to next */