cake
/
libg1m
Archived
1
0
Fork 0

Simplified way MCS files are allocated.

This commit is contained in:
Thomas Touhey 2017-03-06 12:10:35 +01:00
parent 7c90619ffe
commit 6f52a704de
25 changed files with 564 additions and 542 deletions

View File

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

View File

@ -33,6 +33,9 @@
# include <stdlib.h>
# include <stdint.h>
/* ************************************************************************** */
/* 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 */

View File

@ -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;

View File

@ -28,21 +28,28 @@
# define LIBG1M_FORMATUTILS_H
# include <libg1m/format.h>
/* 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 */

View File

@ -28,6 +28,8 @@
# include <stdlib.h>
# include <string.h>
# include <libg1m/internals/endian.h>
# 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); \
}}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

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

View File

@ -21,6 +21,9 @@
* ************************************************************************** */
#include <libg1m/internals.h>
/* ************************************************************************** */
/* 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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -19,50 +19,37 @@
#include <libg1m/internals.h>
/**
* 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);
}

View File

@ -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 */

View File

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

View File

@ -19,6 +19,108 @@
#include <libg1m/internals.h>
#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++;

View File

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

View File

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

View File

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

View File

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