cake
/
libg1m
Archived
1
0
Fork 0
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libg1m/src/manage/mcs.c.draft

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);
}