cake
/
libg1m
Archived
1
0
Fork 0

Arranged some things, corrected GRC decoding.

This commit is contained in:
Thomas Touhey 2017-03-30 14:30:48 +02:00
parent 168d3b1e09
commit a4ff04232d
30 changed files with 492 additions and 239 deletions

View File

@ -31,7 +31,7 @@
# include <libg1m/buffer.h>
# include <libg1m/handle.h>
# include <libg1m/picture.h>
# include <libfontcharacter.h>
# include <libg1m/fontcharacter.h>
# include <stdio.h>
# include <stdint.h>
# include <time.h>

View File

@ -110,7 +110,6 @@ typedef struct bcd {
unsigned char BCDval[9];
unsigned char _align[3];
} mcs_bcd_t;
/* ************************************************************************** */
/* Conversion utilities */
/* ************************************************************************** */

View File

@ -0,0 +1,36 @@
/* *****************************************************************************
* libg1m/fontcharacter.h -- libg1m FONTCHARACTER-related utilities.
* 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/>.
* ************************************************************************** */
#ifndef LIBG1M_FONTCHARACTER_H
# define LIBG1M_FONTCHARACTER_H
# include <libfontcharacter.h>
/* All FONTCHARACTER-related utilities that used to be there were moved into
* a separate library, libfontcharacter, which also takes care of the
* translations (multi-byte/fixed-width, unicode, tokens).
*
* This header is there so the usage of FONTCHARACTER-related utilities in
* libg1m can be more modular.
*
* Here are macros, for later change. */
# define g1m_wctomb(S, WC) (fc_wctomb((S), (WC)))
# define g1m_wcstombs(DST, SRC, N) (fc_wcstombs((DST), (SRC), (N)))
# define g1m_mbtowc(PWC, S, N) (fc_mbtowc((PWC), (S), (N)))
# define g1m_mbstowcs(DST, SRC, N) (fc_mbstowcs((DST), (SRC), (N)))
#endif /* LIBG1M_FONTCHARACTER_H */

View File

@ -87,8 +87,8 @@ struct cas40 {
* pieces of documentation, here are the extension types I could find: */
# define casdyn_ext_9850 0x00 /* 50 bytes long */
# define casdyn_ext_end 0xFF /* 46 bytes long, used with the END packet
* described by Casetta */
# define casdyn_ext_end 0xFF /* yet an alias to `casdyn_ext_9850`,
* used by the END packet. */
# define casdyn_ext_g100 0x31 /* 40 bytes long */
/* Here are the common fields to all packets: */
@ -188,7 +188,10 @@ struct _cas100_info {
* Here are the content formats for the two header types: */
# pragma pack()
# include <libg1m/format/cas/program.h>
# include <libg1m/format/cas/program.h> /* programs, f-mem */
# include <libg1m/format/cas/cell.h> /* list, matrix, variable */
# include <libg1m/format/cas/screenshot.h>
# include <libg1m/format/cas/backup.h>
# include <libg1m/format/cas/picture.h>
# include <libg1m/format/cas/graph.h>
# include <libg1m/format/cas/gmem.h>
#endif /* LIBG1M_FORMAT_CAS_H */

View File

@ -0,0 +1,30 @@
/* *****************************************************************************
* libg1m/format/cas/backup.h -- description of the CAS backup format.
* 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/>.
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_CAS_BACKUP_H
# define LIBG1M_FORMAT_CAS_BACKUP_H
/* Backups are raw backups from the calculator.
*
* The CAS40 specific subheader is basically "TYPE<T>".
* For example, a backup from a CFX-98600G has the "TYPEA" subheader,
* and the editor filename is "02".
*
* TODO: find out the content format. */
#endif /* LIBG1M_FORMAT_CAS_BACKUP_H */

View File

@ -18,7 +18,6 @@
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_CAS_MATRIX_H
# define LIBG1M_FORMAT_CAS_MATRIX_H
# pragma pack(1)
/* Lists, matrixes and variables are sent/stored the same way.
* Variables are either 1*1 matrixes, or 0*0 matrixes if unused.
@ -44,5 +43,4 @@
*
* The order is unknown to me yet. (XXX: todo) */
# pragma pack()
#endif /* LIBG1M_FORMAT_CAS_SCREENSHOT_H */

View File

@ -0,0 +1,70 @@
/* *****************************************************************************
* libg1m/format/cas/gmem.h -- description of the CAS G-MEM format.
* 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/>.
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_CAS_GMEM_H
# define LIBG1M_FORMAT_CAS_GMEM_H
# include <stdint.h>
# pragma pack(1)
/* You can save some graph function's expression inside a graph memory (G-MEM).
* The data size is stored in CAS50's `length` field.
* TODO: find out the equivalent with CAS40 headers?
*
* It starts with 20 graph entries, which have this format: */
struct cas_gmem_entry {
/* function type code */
uint8_t type;
/* flags */
uint8_t flags;
};
/* Where the function types are the following: */
# define cas_gmem_type_ye 0x00 /* Y= */
# define cas_gmem_type_re 0x40 /* r= */
# define cas_gmem_type_yg 0x0C /* Y> */
# define cas_gmem_type_yl 0x0D /* Y< */
# define cas_gmem_type_yge 0x0E /* Y>= */
# define cas_gmem_type_yle 0x0F /* Y<= */
/* And the flags are the following: */
# define cas_gmem_flag_orange 0x01
# define cas_gmem_flag_blue 0x02
# define cas_gmem_flag_green 0x04
# define cas_gmem_flag_sel 0x80
# define cas_gmem_flag_eqsel 0xB0
/* If there are no flags (`entry.flags == 0`), then the function is not defined.
* If the function type is one of: Y=, r=, Param (?)
* Then use `cas_gmem_flag_eqsel` instead of `cas_gmem_flag_sel`.
*
* Then what we have after is the real content of the G-MEM (Y=DATA).
* Each function's expression is separated from the others by a 0xFF character.
* Casetta's documentation says the data is reversed, I don't know what they
* mean (order? bitwise not?).
*
* There are 90 characters at the end of the content. It seems that they don't
* change if you have one or more Y= function defined (independently of the
* function expression).
* TODO: find out what these are. */
# pragma pack()
#endif /* LIBG1M_FORMAT_CAS_GMEM_H */

View File

@ -0,0 +1,44 @@
/* *****************************************************************************
* libg1m/format/cas/graph.h -- description of the CAS graph function format.
* 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/>.
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_CAS_GRAPH_H
# define LIBG1M_FORMAT_CAS_GRAPH_H
/* This is the data type used for the expression of each function which can be
* used to draw a graph. They are sent when you select 'Y=Data' in the
* transfer menu.
* TODO: find out if these have a CAS40 version.
*
* The length of the graph function is stored in `height`.
* The `name` field is the function type, the type and subtype/equality type.
* The type can be one of these: Y, r, Param, X(constant), Y graph function
* The equ. type can be one of these: =, >, <, >=, <=.
*
* Then, possibly at `prefix` (the doc is unclear about this), you have a
* string like 'GR BL SLD YBL NSGT BL NS':
* - 'GR' means graph function;
* - 'BL' is the color code (BL: blue, OR: orange, GR: green);
* - 'SLD' is whether it's selected or not (SLD: selected, NSD: not selected);
* - 'YBL' is another color code (see previous 'BL');
* - 'NSGT' indicates presence of a variable? (sometimes SLGT);
* - 'BL' is another color code (see previous 'BL');
* - 'NS' is linked to 'NSGT' ('NSGT' -> 'NS', 'SLGT' -> 'SL').
*
* The function is FONTCHARACTER-encoded. */
#endif /* LIBG1M_FORMAT_CAS_GRAPH_H */

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* libg1m/format/cas/screenshot.h -- description of the CAS screenshot format.
* libg1m/format/cas/picture.h -- description of the CAS picture format.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -16,8 +16,9 @@
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_CAS_SCREENSHOT_H
# define LIBG1M_FORMAT_CAS_SCREENSHOT_H
#ifndef LIBG1M_FORMAT_CAS_PICTURE_H
# define LIBG1M_FORMAT_CAS_PICTURE_H
# include <stdint.h>
# pragma pack(1)
/* ************************************************************************** */
@ -41,4 +42,4 @@ struct cas_spe_screenshot {
* `g1m_pictureformat_4bit_color` -- see `libg1m/picture.h`. */
# pragma pack()
#endif /* LIBG1M_FORMAT_CAS_SCREENSHOT_H */
#endif /* LIBG1M_FORMAT_CAS_PICTURE_H */

View File

@ -18,12 +18,11 @@
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_CAS_PROGRAM_H
# define LIBG1M_FORMAT_CAS_PROGRAM_H
# include <stdint.h>
# pragma pack(1)
/* ************************************************************************** */
/* CAS40 specific header bytes */
/* ************************************************************************** */
/* In old CAS headers, the five specific bytes are the following: */
/* TODO: describe programs to the newcomer.
* The CAS40 specific header is the following: */
# define casiolink_program_stats 0x02 /* store stats data */
# define casiolink_program_matrix 0x04 /* matrix mode */
@ -39,11 +38,8 @@ struct cas_spe_program {
uint8_t _unknown2;
};
/* ************************************************************************** */
/* Content */
/* ************************************************************************** */
/* The content length is given in the CAS50 header/CAS40 specific bytes.
* It is made of multi-byte FONTCHARACTER characters. */
/* Then the program, using the multi-byte FONTCHARACTER encoding, comes.
* F-MEM (saves of series of commands) are stored like very small programs. */
# pragma pack()
#endif /* LIBG1M_FORMAT_CAS_PROGRAM_H */

View File

@ -18,6 +18,7 @@
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_CASEMUL_H
# define LIBG1M_FORMAT_CASEMUL_H
# include <stdint.h>
# include <libg1m/bcd.h>
# pragma pack(1)

View File

@ -18,7 +18,6 @@
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_FXI_H
# define LIBG1M_FORMAT_FXI_H
# include <libg1m.h>
# include <stdint.h>
# pragma pack(1)

View File

@ -18,6 +18,7 @@
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_MCS_CELLS_H
# define LIBG1M_FORMAT_MCS_CELLS_H
# include <stdint.h>
# include <libg1m/bcd.h>
# pragma pack(1)

View File

@ -18,6 +18,7 @@
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_MCS_PICTURE_H
# define LIBG1M_FORMAT_MCS_PICTURE_H
# include <stdint.h>
# pragma pack(1)
/* Captures start with a simple header: */

View File

@ -18,7 +18,8 @@
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_MCS_PROGRAM_H
# define LIBG1M_FORMAT_MCS_PROGRAM_H
# include <libfontcharacter.h>
# include <stdint.h>
# include <libg1m/fontcharacter.h>
# pragma pack(1)
/* Programs have a simple header: */

View File

@ -18,6 +18,7 @@
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_MCS_SPREADSHEET_H
# define LIBG1M_FORMAT_MCS_SPREADSHEET_H
# include <stdint.h>
# include <libg1m/bcd.h>
# pragma pack(1)

View File

@ -19,6 +19,7 @@
#ifndef LIBG1M_FORMAT_STD_EACT_H
# define LIBG1M_FORMAT_STD_EACT_H
# include <stdint.h>
# pragma pack(1)
/* E-Activities are the format CASIO uses for in-calc documents.
* It is the funniest subformat the the libg1m can parse.
@ -131,4 +132,5 @@ struct line_descriptor {
*
* Which means in each node, there can be a content to parse. */
# pragma pack()
#endif /* LIBG1M_FORMAT_STD_EACT_H */

View File

@ -18,7 +18,7 @@
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_STD_FKEY_H
# define LIBG1M_FORMAT_STD_FKEY_H
# include <libg1m.h>
# include <stdint.h>
# pragma pack(1)
/* Function keys are the little boxes at the bottom with text in it, to tell

View File

@ -18,7 +18,7 @@
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_STD_LANG_H
# define LIBG1M_FORMAT_STD_LANG_H
# include <libg1m.h>
# include <stdint.h>
# pragma pack(1)
/* ************************************************************************** */

View File

@ -77,8 +77,8 @@ typedef unsigned int g1m_mcsinfo_t;
g1m_mcstype_list | g1m_mcstype_mat | g1m_mcstype_vct | \
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)
# define g1m_get_id_major(I) ((I) >> 6)
# define g1m_get_id_minor(I) ((I) & 0x3F)
/* ************************************************************************** */
/* Helpers */
/* ************************************************************************** */

View File

@ -22,10 +22,17 @@
#include <libg1m/internals.h>
#define FUNC(NAME) g1m_decode_caspart_##NAME
#define HFUNC(NAME) g1m_decode_cashpart_##NAME
#define READGSIZE() if (grc) { \
uint16_t size; READ(&size, 2) \
log_info("GraphCard next buffer size was: 0x%04X", be16toh(size)); }
#define READCOLON() { \
READGSIZE() \
uint8_t colon; GREAD(&colon, 1) \
err = g1m_error_magic; \
if (colon != ':') goto fail; }
if (colon != ':') { \
log_error("Expected ':', got '%c' (0x%02X)", colon, colon); \
goto fail; \
}}
/* ************************************************************************** */
/* Type correspondance list */
@ -83,7 +90,7 @@ static void *lookup_cas_decode(g1m_mcstype_t type, int heads)
* Decode a CASIOLINK Protocol header.
*
* @arg head the head to fill.
* @arg hd the header.
* @arg buffer the buffer to read from.
* @arg csum the current checksum.
* @return if there was an error, or not.
*/
@ -98,10 +105,15 @@ static int decode_cas50(g1m_mcshead_t *head, g1m_buffer_t *buffer, uint8_t csum)
/* check the checksum */
csum += g1m_checksum8(&hd, sizeof(struct _cas50) - 1);
if (~csum + 1 != hd.checksum)
csum = ~csum + 1;
if (csum != hd.checksum) {
log_error("Checksum mismatch: expected 0x%02X, got 0x%02X",
hd.checksum, csum);
return (g1m_error_checksum);
}
/* copy the basic information */
g1m_maketype_cas(head, (char*)hd.data);
head->size = be16toh(hd.height) - 2 /* checksum, colon */;
char *end = memchr(hd.name, 0xFF, 8);
size_t len = end ? (size_t)(end - (char*)hd.name) : 8;
@ -238,10 +250,10 @@ int g1m_decode_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer)
}
/* ************************************************************************** */
/* File decoding function */
/* Main file decoding function */
/* ************************************************************************** */
/**
* g1m_decode_cas:
* decode_cas:
* Decode a CAS file.
*
* Is also sort of a guide for using the CAS MCS files.
@ -249,16 +261,20 @@ int g1m_decode_casfile_part(g1m_mcsfile_t *file, g1m_buffer_t *buffer)
*
* @arg h the handle to create.
* @arg buffer the buffer to read from.
* @arg grc is a graphcard file.
* @return the libg1m error.
*/
int g1m_decode_cas(g1m_handle_t **h, g1m_buffer_t *buffer)
static int decode_cas(g1m_handle_t **h, g1m_buffer_t *buffer, int grc)
{
/* make the handle */
int err = g1m_make_mcs(h, 0);
if (err) return (err);
g1m_handle_t *handle = *h;
/* read first colon */
if (grc) READCOLON() /* FIXME: read this in graphcard magic? */
/* read each */
for (handle->count = 0;;) {
/* read the head */
@ -317,6 +333,23 @@ fail:
return (err);
}
/* ************************************************************************** */
/* Public decoding functions */
/* ************************************************************************** */
/**
* g1m_decode_cas:
* Decode a CAS file.
*
* @arg handle the handle to make.
* @arg buffer the buffer to read from.
* @return the libg1m error.
*/
int g1m_decode_cas(g1m_handle_t **handle, g1m_buffer_t *buffer)
{
return (decode_cas(handle, buffer, 0));
}
/**
* g1m_decode_grc:
* Decode Graph Card file.
@ -328,7 +361,16 @@ fail:
int g1m_decode_grc(g1m_handle_t **handle, g1m_buffer_t *buffer)
{
uint8_t intro[2]; READ(intro, 2) /* probably the file count? */
uint8_t colon; READ(&colon, 1) /* read first colon */
return (g1m_decode_cas(handle, buffer));
/* file decoding */
int err = decode_cas(handle, buffer, 1);
if (err) return (err);
/* read final size */
uint16_t final; GREAD(&final, sizeof(uint16_t))
if (final != 0) return (g1m_error_magic);
return (0);
fail:
g1m_free(*handle); *handle = NULL;
return (err);
}

View File

@ -109,7 +109,7 @@ int g1m_decode_caspart_var(g1m_mcsfile_t *handle, g1m_buffer_t *buffer)
unsigned int x, y;
int err = decode_cell(buffer, &handle->var, &x, &y);
if (err) return (err);
if (x != 0 || y != 0) return (g1m_error_magic);
if (x != 1 || y != 1) return (g1m_error_magic);
/* no error! */
handle->head.flags &= ~g1m_mcsflag_unfinished;

View File

@ -39,8 +39,11 @@ int g1m_decode_cashpart_program(g1m_mcshead_t *head, g1m_mcshead_t *heads,
uint8_t checksum; READ(&checksum, 1)
uint8_t csum = ~g1m_checksum8(headers,
sizeof(struct cas_spe_program) * head->count) + 1;
if (csum != checksum)
if (csum != checksum) {
log_error("Checksum mismatch: expected 0x%02X, got 0x%02X",
csum, checksum);
return (g1m_error_checksum);
}
/* initialize */
for (int i = 0; i < head->count; i++) {
@ -72,8 +75,11 @@ int g1m_decode_caspart_program(g1m_mcsfile_t *handle, g1m_buffer_t *buffer)
/* check the sum */
uint8_t checksum; READ(&checksum, 1)
uint8_t csum = ~g1m_checksum8(handle->content, handle->head.size) + 1;
if (csum != checksum)
if (csum != checksum) {
log_error("Checksum mismatch: expected 0x%02X, got 0x%02X",
csum, checksum);
return (g1m_error_checksum);
}
/* everything went well :) */
handle->head.flags &= ~g1m_mcsflag_unfinished;

195
src/decode/mcs.c Normal file
View File

@ -0,0 +1,195 @@
/* *****************************************************************************
* decode/mcs.c -- decode an MCS file.
* 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>
#include <stdlib.h>
#define FUNC(NAME) g1m_decode_mcs_##NAME
/* ************************************************************************** */
/* Type correspondance list */
/* ************************************************************************** */
/* MCS file parsing function type */
typedef int (*mcs_decode_func_t)(g1m_mcsfile_t**, g1m_buffer_t*,
g1m_mcshead_t*);
/* Correspondance type */
struct mcs_corresp {
unsigned int type;
mcs_decode_func_t decode;
};
/* All correspondances */
#define TTERM {0, NULL}
static struct mcs_corresp mcs_types[] = {
{g1m_mcstype_program, FUNC(program)},
{g1m_mcstype_list, FUNC(cells)},
{g1m_mcstype_mat, FUNC(cells)},
{g1m_mcstype_vct, FUNC(cells)},
{g1m_mcstype_spreadsheet, FUNC(spreadsheet)},
{g1m_mcstype_pict, FUNC(picture)},
{g1m_mcstype_capt, FUNC(capture)},
{g1m_mcstype_string, FUNC(string)},
{g1m_mcstype_setup, FUNC(setup)},
{g1m_mcstype_alphamem, FUNC(var)},
{g1m_mcstype_variable, FUNC(var)},
TTERM
};
/**
* lookup_mcsfile_decode:
* Lookup for a parsing function for an MCS file type.
*
* @arg type the libg1m MCS file type.
* @return the function (NULL if not found).
*/
static mcs_decode_func_t lookup_mcsfile_decode(g1m_mcstype_t type)
{
/* lookup for the type */
struct mcs_corresp *c = mcs_types;
while (c->decode) {
if (type == c->type)
break;
c++;
}
/* return the function */
return (c->decode);
}
/* ************************************************************************** */
/* Head decoding function */
/* ************************************************************************** */
/**
* g1m_decode_mcsfile_head:
* Decode MCS file head.
*
* @arg head the head to fill.
* @arg raw_type the raw file type.
* @arg groupname the groupname (up to 16 bytes).
* @arg dirname the directory name (up to 8 bytes).
* @arg filename the filename (up to 8 bytes).
* @arg filesize the data length.
* @return 0 if the head was filled with success, -1 otherwise.
*/
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)
{
/* check that we have a head, lol */
if (!head) return (-1);
/* look for the raw type */
g1m_maketype_mcs(head, (char*)groupname, (char*)dirname,
(char*)filename, raw_type);
head->size = filesize;
log_info("libg1m file type is 0x%08" PRIXMCSTYPE, head->type);
#if LOGLEVEL <= ll_info
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
/* everything went well! */
return (0);
}
/* ************************************************************************** */
/* File decoding functions */
/* ************************************************************************** */
/**
* g1m_decode_mcsfile:
* Decode MCS file content.
*
* Part of the public API because of the Protocol 7, where file is sent
* without its header (only with specific subheaders).
*
* @arg handle the handle to make.
* @arg head the head to use.
* @arg buffer the buffer to read from.
* @return the error code (0 if ok).
*/
int g1m_decode_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *head,
g1m_buffer_t *buffer)
{
int err = 0;
/* check that the head is there */
if (!head) return (g1m_error_op);
g1m_mcshead_t h = *head;
/* look for the decoding function */
mcs_decode_func_t decode = lookup_mcsfile_decode(head->type);
if (!decode) {
log_error("No dedicated decoding function for this type was found!");
goto notparsing;
}
/* decode */
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)
}
/* oh yeah, and go away. */
if (err) goto fail;
return (0);
notparsing:
/* allocate enough space */
if ((err = g1m_make_mcsfile(handle, &h)))
return (err);
/* read the content */
GREAD((*handle)->content, h.size)
/* log */
log_info("File content:");
logm_info((*handle)->content, h.size);
/* saved normally */
return (0);
fail:
g1m_free_mcsfile(*handle);
return (err);
}
/**
* g1m_decode_mcsfile_data:
* Decode a MCS file content from raw memory.
*
* @arg handle the file handle.
* @arg head the file head.
* @arg data the buffer data.
* @arg size the buffer size.
* @return the libg1m error.
*/
int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle,
const g1m_mcshead_t *head, const unsigned char *data, size_t size)
{
g1m_buffer_t membuf = MEMBUFFER(data, size);
return (g1m_decode_mcsfile(handle, head, &membuf));
}

View File

@ -297,13 +297,13 @@ static int eact_decode_line_picture(g1m_line_t *handle, uint8_t *buf,
while (*(++p)) *p = be16toh(*p);
/* get the size of the multi-byte string */
size_t sz = fc_wcstombs(NULL, s, 0);
size_t sz = g1m_wcstombs(NULL, s, 0);
if (sz == (size_t)-1) return (g1m_error_magic);
/* make the string */
handle->content = malloc(sizeof(FONTCHARACTER) * (sz + 1));
if (!handle->content) return (g1m_error_alloc);
fc_wcstombs(handle->content, s, 0);
g1m_wcstombs(handle->content, s, 0);
/* don't forget to set the handle type! */
handle->type = g1m_linetype_picture;

View File

@ -18,185 +18,7 @@
* ************************************************************************** */
#include <libg1m/internals.h>
#include <stdlib.h>
#define FUNC(NAME) g1m_decode_mcs_##NAME
/* ************************************************************************** */
/* Type correspondance list */
/* ************************************************************************** */
/* MCS file parsing function type */
typedef int (*mcs_decode_func_t)(g1m_mcsfile_t**, g1m_buffer_t*,
g1m_mcshead_t*);
/* Correspondance type */
struct mcs_corresp {
unsigned int type;
mcs_decode_func_t decode;
};
/* All correspondances */
#define TTERM {0, NULL}
static struct mcs_corresp mcs_types[] = {
{g1m_mcstype_program, FUNC(program)},
{g1m_mcstype_list, FUNC(cells)},
{g1m_mcstype_mat, FUNC(cells)},
{g1m_mcstype_vct, FUNC(cells)},
{g1m_mcstype_spreadsheet, FUNC(spreadsheet)},
{g1m_mcstype_pict, FUNC(picture)},
{g1m_mcstype_capt, FUNC(capture)},
{g1m_mcstype_string, FUNC(string)},
{g1m_mcstype_setup, FUNC(setup)},
{g1m_mcstype_alphamem, FUNC(var)},
{g1m_mcstype_variable, FUNC(var)},
TTERM
};
/**
* lookup_mcsfile_decode:
* Lookup for a parsing function for an MCS file type.
*
* @arg type the libg1m MCS file type.
* @return the function (NULL if not found).
*/
static mcs_decode_func_t lookup_mcsfile_decode(g1m_mcstype_t type)
{
/* lookup for the type */
struct mcs_corresp *c = mcs_types;
while (c->decode) {
if (type == c->type)
break;
c++;
}
/* return the function */
return (c->decode);
}
/* ************************************************************************** */
/* Head decoding function */
/* ************************************************************************** */
/**
* g1m_decode_mcsfile_head:
* Decode MCS file head.
*
* @arg head the head to fill.
* @arg raw_type the raw file type.
* @arg groupname the groupname (up to 16 bytes).
* @arg dirname the directory name (up to 8 bytes).
* @arg filename the filename (up to 8 bytes).
* @arg filesize the data length.
* @return 0 if the head was filled with success, -1 otherwise.
*/
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)
{
/* check that we have a head, lol */
if (!head) return (-1);
/* look for the raw type */
g1m_maketype_mcs(head, (char*)groupname, (char*)dirname,
(char*)filename, raw_type);
head->size = filesize;
log_info("libg1m file type is 0x%08" PRIXMCSTYPE, head->type);
#if LOGLEVEL <= ll_info
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
/* everything went well! */
return (0);
}
/* ************************************************************************** */
/* File decoding functions */
/* ************************************************************************** */
/**
* g1m_decode_mcsfile:
* Decode MCS file content.
*
* Part of the public API because of the Protocol 7, where file is sent
* without its header (only with specific subheaders).
*
* @arg handle the handle to make.
* @arg head the head to use.
* @arg buffer the buffer to read from.
* @return the error code (0 if ok).
*/
int g1m_decode_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *head,
g1m_buffer_t *buffer)
{
int err = 0;
/* check that the head is there */
if (!head) return (g1m_error_op);
g1m_mcshead_t h = *head;
/* look for the decoding function */
mcs_decode_func_t decode = lookup_mcsfile_decode(head->type);
if (!decode) {
log_error("No dedicated decoding function for this type was found!");
goto notparsing;
}
/* decode */
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)
}
/* oh yeah, and go away. */
if (err) goto fail;
return (0);
notparsing:
/* allocate enough space */
if ((err = g1m_make_mcsfile(handle, &h)))
return (err);
/* read the content */
GREAD((*handle)->content, h.size)
/* log */
log_info("File content:");
logm_info((*handle)->content, h.size);
/* saved normally */
return (0);
fail:
g1m_free_mcsfile(*handle);
return (err);
}
/**
* g1m_decode_mcsfile_data:
* Decode a MCS file content from raw memory.
*
* @arg handle the file handle.
* @arg head the file head.
* @arg data the buffer data.
* @arg size the buffer size.
* @return the libg1m error.
*/
int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle,
const g1m_mcshead_t *head, const unsigned char *data, size_t size)
{
g1m_buffer_t membuf = MEMBUFFER(data, size);
return (g1m_decode_mcsfile(handle, head, &membuf));
}
/* ************************************************************************** */
/* Main file function */
/* ************************************************************************** */
/**
* g1m_decode_std_mcs:
* Decode an MCS file, after the Standard Header.

View File

@ -115,8 +115,7 @@ int g1m_make_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *rawhead)
/* finish */
return (0);
fail:
free(h);
*handle = NULL;
free(*handle); *handle = NULL;
return (g1m_error_alloc);
}

View File

@ -34,6 +34,9 @@ struct ext_corresp {
/* identification */
int value;
/* things */
g1m_mcsinfo_t info;
/* app correspondances */
struct app_corresp *apps;
};
@ -47,7 +50,7 @@ struct ext_corresp {
#define ETERM {NULL}
static struct ext_corresp apps[] = {
/* CFX-9850G headers (very first headers with this extension system?) */
{casdyn_ext_9850, (struct app_corresp[]){
{casdyn_ext_9850, g1m_mcsinfo_cas50, (struct app_corresp[]){
{"TXT"}, /* editor */
{"VAL"}, /* RUN? */
{"IMG"}, /* screen shooter? */
@ -55,15 +58,15 @@ static struct ext_corresp apps[] = {
ETERM
}},
/* some sort of format only used with the END packet, I suppose? */
{casdyn_ext_end, (struct app_corresp[]){
/* CFX-9850G header alias, used with the END packet only */
{casdyn_ext_end, g1m_mcsinfo_cas50, (struct app_corresp[]){
{"END"}, /* end packet... used in the same period than 9850G packets? */
ETERM
}},
/* Graph 100 (Algebra FX) headers */
{casdyn_ext_g100, (struct app_corresp[]){
{casdyn_ext_g100, g1m_mcsinfo_cas100, (struct app_corresp[]){
{"ADN"}, /* ? */
{"MCS"}, /* ? */
{"MDL"}, /* model info? */
@ -73,7 +76,7 @@ static struct ext_corresp apps[] = {
}},
/* sentinel */
{0, NULL}
{0, 0, NULL}
};
/* ************************************************************************** */
@ -109,7 +112,8 @@ int g1m_maketype_casapp(g1m_mcshead_t *head,
/* copy raw information */
memset(head, 0, sizeof(g1m_mcshead_t));
head->info = g1m_mcsinfo_graph100; /* FIXME */
head->info = e->info; /* FIXME */
log_info("Head info is 0x%04X", e->info);
strncpy((char*)head->_appname, app, 3);
head->_appname[3] = 0;

View File

@ -58,30 +58,28 @@ static struct type_corresp cas_groups[] = {
/* programs */
{"P", arg | arg_is_num, g1m_mcstype_program, 0},
{"PZ", mult | noarg, g1m_mcstype_program, 0},
{"PZ", mult | noarg, g1m_mcstype_program, 0}, /* 38 programs: 0-9,A-Z,... */
/* captures */
CAPT("DC", g1m_pictureformat_4bit_color),
CAPT("DD", g1m_pictureformat_4bit_mono),
/* not implemented yet */
/* decoding is being implemented */
UNIMPLEMENTED("GF"), /* graph zoom factor (graph function?) */
UNIMPLEMENTED("AA"), /* dynamic graph functions */
UNIMPLEMENTED("BU"), /* backup */
/* not implemented yet */
UNIMPLEMENTED("AD"), /* variable memory */
UNIMPLEMENTED("AL"), /* all */
UNIMPLEMENTED("AM"), /* alpha variable memory */
UNIMPLEMENTED("BU"), /* backup */
UNIMPLEMENTED("DM"), /* defined memory */
UNIMPLEMENTED("EN"), /* one editor file */
UNIMPLEMENTED("FN"), /* set of editor files */
UNIMPLEMENTED("FT"), /* ??? (cafix) */
UNIMPLEMENTED("F1"), /* one function memory */
UNIMPLEMENTED("F6"), /* set of function memories */
UNIMPLEMENTED("GA"), /* set of graph functions */
UNIMPLEMENTED("GF"), /* graph zoom factor (graph function?) */
UNIMPLEMENTED("GM"), /* gmem (cafix) */
UNIMPLEMENTED("GR"), /* graph range */
UNIMPLEMENTED("GT"), /* function table */
UNIMPLEMENTED("MA"), /* set of matrices */
UNIMPLEMENTED("PC"), /* picture from 9xxx (cafix) */
UNIMPLEMENTED("PD"), /* polynomial equations */
UNIMPLEMENTED("RF"), /* ??? (cafix) */
@ -94,6 +92,12 @@ static struct type_corresp cas_groups[] = {
UNIMPLEMENTED("TR"), /* ??? (cafix) */
UNIMPLEMENTED("WD"), /* window data (cafix) */
/* sets */
UNIMPLEMENTED("FN"), /* set of editor files */
UNIMPLEMENTED("F6"), /* set of function memories */
UNIMPLEMENTED("GA"), /* set of graph functions */
UNIMPLEMENTED("MA"), /* set of matrices */
/* terminating entry */
TTERM
};

View File

@ -131,14 +131,12 @@ static struct group_corresp mcs_groups[] = {
TTERM
}},
/* more or less main memory */
/* application-specific data */
{"CAPT ", arg | arg_is_num, (struct type_corresp[]){
{0x0A, "CAPT", arg | arg_is_num, "@REV2",
"capture", g1m_mcstype_capt},
TTERM
}},
/* application-specific data */
{"SYSTEM", noarg, (struct type_corresp[]){
{0xFE, NULL /* REPLAY/RUN2D1 */, 0, "@RUNMAT",
"replay", 0x00},
@ -360,7 +358,7 @@ int g1m_maketype_mcs(g1m_mcshead_t *head,
&& get_number(&fname[fl], &fid, t->flags & arg_is_num))
continue;
if (t->flags & weight_by_gid)
fid |= (gid << 5);
fid |= (gid << 6);
}
break;
}