231 lines
6.5 KiB
Plaintext
231 lines
6.5 KiB
Plaintext
/* *****************************************************************************
|
|
* manage/mcs.c -- manage an MCS archive handle.
|
|
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
* ************************************************************************** */
|
|
#include <libg1m/internals.h>
|
|
#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_correct_mcsfile_head(&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);
|
|
}
|