/* ***************************************************************************** * manage/mcs.c -- manage an MCS archive 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 #define MCS_CHUNK_SIZE 16 /* ************************************************************************** */ /* Internal functions */ /* ************************************************************************** */ /** * find_space_for_file: * Find space for some element function. * * @arg handle the handle. * @arg type the type. * @arg name the name. * @arg id the ID. * @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) { g1m_mcsfile_t **pfile = NULL; /* look if this file isn't already in the tab */ for (int i = 0; i < handle->count; i++) { g1m_mcsfile_t *file = handle->files[i]; if (!file) { pfile = &handle->files[i]; continue; } if ((file->head.type & type) && (id ? file->head.id == id : !strcmp(file->head.name, name))) { g1m_free_mcsfile_content(file); pfile = &handle->files[i]; goto found; } } /* if no empty space was found, take one at the end (allocate if needed) */ if (!pfile) { if (handle->count >= handle->_size) { handle->_size = handle->count + MCS_CHUNK_SIZE; handle->files = realloc(handle->files, handle->_size * sizeof(g1m_mcsfile_t**)); if (!handle->files) return (NULL); } 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_mcstype_correct(&file->head); /* return it */ return (file); } /* ************************************************************************** */ /* Public functions */ /* ************************************************************************** */ /** * g1m_putmcs_program: * Put a program in a MCS handle. * * @arg handle the handle. * @arg pfile pointer to the file pointer to set. * @arg name the name of the program. * @arg password the password (NULL if none). * @return the error code (0 if ok). */ int g1m_putmcs_program(g1m_t *handle, g1m_mcsfile_t **pfile, char *name, char *password, char *content) { /* check if the operation is supported */ 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); 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); } /** * g1m_putmcs_capture: * Put a capture in an MCS handle. * * @arg handle the handle. * @arg pfile the file pointer to get file. * @arg id the capture ID (1 to 20). * @arg width the capture width. * @arg height the capture height. * @arg pic the pixels to copy. * @return the error code (0 if ok). */ int g1m_putmcs_capture(g1m_t *handle, g1m_mcsfile_t **pfile, int id, int width, int height, uint32_t **pic) { /* check if the operation is supported */ if (~handle->type & g1m_type_mcs || id < 1 || id > 20) return (g1m_error_op); /* find the file */ g1m_mcsfile_t *file = find_space_for_file(handle, g1m_mcstype_capture, NULL, id); 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]; for (int y = 0; y < height; y++) { uint32_t *line = *pic++; for (int x = 0; x < width; x++) *pix++ = *line++; } /* no error */ if (pfile) *pfile = file; return (0); } /** * g1m_putmcs_picture: * Put a picture in an MCS handle. * * @arg handle the handle. * @arg pfile the file pointer to get. * @arg id the picture ID (1 to 20). * @arg pic_one pixels of the first 128x64 image to copy. * @arg pic_two pixels of the second 128x64 image to copy. * @return the error code (0 if ok). */ int g1m_putmcs_picture(g1m_t *handle, g1m_mcsfile_t **pfile, int id, uint32_t **pic_one, uint32_t **pic_two) { /* check if the operation is supported */ if (~handle->type & g1m_type_mcs || id < 1 || id > 20) return (g1m_error_op); /* find the file */ g1m_mcsfile_t *file = find_space_for_file(handle, g1m_mcstype_picture, NULL, id); 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]; for (int y = 0; y < 64; y++) { uint32_t *line_one = *pic_one++; uint32_t *line_two = *pic_two++; for (int x = 0; x < 128; x++) { *one++ = *line_one++; *two++ = *line_two++; } } /* no error */ if (pfile) *pfile = file; return (0); }