cake
/
libg1m
Archived
1
0
Fork 0

Corrected CAS management... I should read more before coding.

This commit is contained in:
Thomas Touhey 2017-02-25 05:05:48 +01:00
parent b0564bb32b
commit 3f000c4f30
8 changed files with 148 additions and 45 deletions

View File

@ -94,7 +94,8 @@ int g1m_decode_mcsfile(g1m_mcsfile_t **handle,
const g1m_mcshead_t *head, g1m_buffer_t *buffer);
/* open CAS head/file */
int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer);
int g1m_decode_casfile_head(g1m_mcshead_t *head,
const char *datatype, const char *filename, const char *specific);
int g1m_decode_casfile(g1m_mcsfile_t **handle,
const g1m_mcshead_t *head, g1m_buffer_t *buffer);

View File

@ -22,13 +22,57 @@
# include <stdint.h>
# pragma pack(1)
/* The CASIOLINK format is linked to the legacy communication protocol.
* It is basically a MCS file.
/* The CASIOLINK format looks a lot like the legacy communication protocol,
* but the two are to distinguish. A CASIOLINK-encoded file is basically
* a set of one or more MCS files of the same type.
*
* The file has two main parts.
* The file has two parts, each starting with a 0x3A (':').
* It starts with a header: */
struct casiolink_header {
uint8_t data[2];
uint8_t _specific[5]; /* type-specific subheader */
uint8_t filename[12]; /* unused chars are filled with 0xFFs. */
uint8_t _unused[19]; /* 0xFFs. */
uint8_t checksum;
};
/* For a program, the specific bytes are the following: */
# define casiolink_program_uk0 0x01 /* <unknown> */
# define casiolink_program_stats 0x02 /* store stats data */
# define casiolink_program_matrix 0x04 /* matrix mode */
# define casiolink_program_uk1 0x08 /* <unknown */
# define casiolink_program_stddev 0x10 /* standard deviation mode */
# define casiolink_program_linreg 0x20 /* linear regression mode */
# define casiolink_program_basen 0x40 /* base-n mode */
# define casiolink_program_drawst 0x80 /* draw stats graph */
struct casiolink_spe_program {
uint8_t _unknown;
uint16_t length;
uint8_t flags;
uint8_t _unknown2;
};
/* The specific bytes are the same for a set of programs, but `flags` is
* not used, and the length is the size of all of the programs put together.
*
* Now, here are the specific bytes for a screenshot: */
struct casiolink_spe_screenshot {
uint8_t height;
uint8_t width;
uint8_t _unused[3];
};
/* The specific bytes for a number start with either "RA" or "CA", 'R' or 'C'
* meaning the number is complex or not. */
/* This should be put somewhere else, as it represents the packets in
* a legacy protocol communication. (FIXME: maybe the new CAS header?) */
struct casiolink_new_header {
/* types */
uint8_t type[4];
uint8_t data[4];

View File

@ -41,6 +41,6 @@ int g1m_mcstype_toraw(unsigned int type, int id,
char *name, char *dirname, char *groupname);
/* get cas type data */
int g1m_castype_get(const char *rawtype, const char *data, unsigned int *type);
int g1m_castype_get(const char *datatype, unsigned int *type);
#endif /* LIBG1M_FORMATUTILS_H */

View File

@ -139,6 +139,7 @@ void g1m_free_line_content(g1m_line_t *line);
int g1m_skip(g1m_buffer_t *buffer, size_t size, uint_fast32_t *checksum);
/* Checksum-ing */
uint8_t g1m_checksum8(void *mem, size_t size);
uint32_t g1m_checksum32(void *mem, size_t size, uint32_t checksum);
/* File buffer */

View File

@ -40,7 +40,6 @@ typedef unsigned int g1m_mcstype_t;
# define g1m_mcstype_setup 0x0080
# define g1m_mcstype_alphamem 0x0100
# define g1m_mcstype_vct 0x0200
# define g1m_mcstype_end 0x0400
/* MCS file type aliases */
# define g1m_mcstype_picture g1m_mcstype_pict
@ -71,7 +70,7 @@ typedef struct g1m_mcs_cell_s {
typedef struct g1m_mcshead_s {
/* file main information */
g1m_mcstype_t type;
char name[9]; int id;
char name[13]; int id;
/* content size */
uint_fast32_t size;

View File

@ -29,36 +29,33 @@
* Decode the CAS file head.
*
* @arg head the head to decode.
* @arg buffer the buffer to read from.
* @arg datatype the raw data type (at least 2 bytes).
* @arg filename the file name (at least 12 bytes).
* @arg specific the specific bytes (at least 5 bytes).
* @return the error code (0 if ok).
*/
int g1m_decode_casfile_head(g1m_mcshead_t *head, g1m_buffer_t *buffer)
int g1m_decode_casfile_head(g1m_mcshead_t *head, const char *datatype,
const char *filename, const char *specific)
{
/* check that the head exists */
if (!head) return (-1);
/* Declare the header */
struct casiolink_header hd;
uint8_t * const uhd = (void*)&hd;
/* get the type and datatype */
READ(&hd, 8)
if (g1m_castype_get((char*)hd.type, (char*)hd.data, &head->type))
return (g1m_error_unknown);
/* finish reading
* FIXME: sometimes, packet isn't 49 bytes long! */
READ(&uhd[8], 41)
/* check the sum */
uint8_t checksum = 0;
for (int i = 0; i < 48; i++) checksum += uhd[i];
if (checksum != hd.checksum) return (g1m_error_magic);
/* check the data type */
if (g1m_castype_get(datatype, &head->type))
return (g1m_error_unrecognized);
/* fill the handle */
memcpy(head->name, hd.name, 8); head->name[8] = 0;
head->size = hd.length;
memset(head->_dirname, 0, 9);
memset(head->_group, 0, 17);
memcpy(head->name, filename, 12); head->name[12] = 0;
/* type specific */
if (head->type == g1m_mcstype_program) {
struct casiolink_spe_program *spe = (void*)specific;
head->size = be16toh(spe->length);
/* TODO: store flags? */
}
/* no error! */
return (0);
@ -82,8 +79,17 @@ int g1m_decode_cas(g1m_t *handle, g1m_buffer_t *buffer,
{
int err;
/* read the header */
DREAD(hd, casiolink_header)
if (g1m_checksum8(&hd, sizeof(struct casiolink_header) - 1) != hd.checksum)
return (g1m_error_checksum);
/* decrypt it */
g1m_mcshead_t head;
if ((err = g1m_decode_casfile_head(&head, buffer)))
if ((err = g1m_decode_casfile_head(&head, (char*)hd.data,
(char*)hd.filename, (char*)hd._specific)))
return (err);
/* everything went fine :) */
return (0);
}

View File

@ -25,8 +25,7 @@
/* Correspondance type */
struct type_corresp {
/* identification */
const char *rawtype;
const char *rawdata;
const char *datatype;
/* libg1m MCS file type */
unsigned int type;
@ -39,10 +38,48 @@ struct type_corresp {
* - Correspondances with a NULL data type means the data type isn't to be
* read. */
#define TTERM {NULL, NULL, 0}
#define TTERM {NULL, 0}
static struct type_corresp cas_groups[] = {
{"TXT", "PG", g1m_mcstype_program},
{"END", NULL, g1m_mcstype_end},
/* not implemented yet types, described by Tom Wheeley and Tom Lynn */
{"AA", 0}, // dynamic graph functions
{"AD", 0}, // variable memory
{"AL", 0}, // all
{"AM", 0}, // alpha variable memory
{"BU", 0}, // backup
{"DM", 0}, // defined memory
{"DD", 0}, // screenshot
{"EN", 0}, // one editor file
{"FN", 0}, // set of editor files
{"F1", 0}, // one function memory
{"F6", 0}, // set of function memories
{"GA", 0}, // set of graph functions
{"GF", 0}, // graph zoom factor (graph function?)
{"GR", 0}, // graph range
{"GT", 0}, // function table
{"MA", 0}, // set of matrices
{"PD", 0}, // polynomial equations
{"P1", 0}, // one program
{"PZ", 0}, // set of programs
{"RT", 0}, // recursion table
{"SD", 0}, // simultaneous equations
{"SR", 0}, // linear regression data
{"SS", 0}, // standard deviation data
/* not implemented yet types, described in libcafix */
{"FT", 0}, // ???
{"GM", 0}, // G-Mem?
{"LT", 0}, // List
{"MT", 0}, // Matrix
{"PC", 0}, // Picture
{"RF", 0}, // ???
{"RR", 0}, // ???
{"SE", 0}, // Equation?
{"TR", 0}, // ???
{"VM", 0}, // Variable (A-Z, etc)
{"WD", 0}, // window data
/* implemented types */
{"PG", g1m_mcstype_program},
TTERM
};
@ -53,31 +90,28 @@ static struct type_corresp cas_groups[] = {
* g1m_castype_get:
* Get the libg1m MCS type from raw CAS identification data.
*
* @arg rawtype the raw type string.
* @arg data the data type string.
* @arg datatype the data type string.
* @arg type[out] the libg1m MCS type.
* @return the error (if any).
*/
int g1m_castype_get(const char *rawtype, const char *data, unsigned int *type)
int g1m_castype_get(const char *datatype, unsigned int *type)
{
struct type_corresp *c = cas_groups - 1;
while ((++c)->rawtype) {
if (strncmp(rawtype, c->rawtype, 4))
continue;
if (c->rawdata && strncmp(data, c->rawdata, 4))
while ((++c)->datatype) {
if (c->datatype && strncmp(datatype, c->datatype, 4))
continue;
break;
}
if (!c->rawtype) goto notfound;
if (!c->type) goto notfound;
/* fill in info and return */
if (type) *type = c->type;
return (0);
notfound:
log_info("Type with '%.4s' type string and '%.4s' data string "
"wasn't recognized.", rawtype, data);
log_info("Type with '%.4s' data string was not implemented or not "
"recognized.", datatype);
if (type) *type = 0;
return (1);
}

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* utils/checksum32.c -- make a checksum on 32-bits out of a memory zone.
* utils/checksum.c -- checksum utilities.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -18,6 +18,24 @@
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* g1m_checksum8:
* Make a simple 8-bit checksum.
*
* @arg mem the memory zone.
* @arg size the memory zone size.
* @return the checksum
*/
uint8_t g1m_checksum8(void *mem, size_t size)
{
uint8_t *m = mem, c = 0;
while (size--)
c += *m++;
return (c);
}
/**
* g1m_checksum32:
* Make checksums great again.