Corrected MCS head management.
This commit is contained in:
parent
931e14f1fd
commit
23f40d1695
|
@ -2,8 +2,9 @@
|
|||
Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
|
||||
|
||||
The documentation comes from a lot of places in the CASIO community, but mainly
|
||||
from **Casiopeia** (mainly with Simon Lothar's documentation) and **Cemetech**
|
||||
(Prizm-related formats).
|
||||
from **Casiopeia** (mainly with Simon Lothar's documentation), **Cemetech**
|
||||
(Prizm-related formats) and the **Casetta project documentation**
|
||||
(reunion of five to twenty years old documentation).
|
||||
|
||||
Thanks to Simon Lothar, Teamfx and KermMartian for their help!
|
||||
Thanks to the people on **Planète Casio** for their support!
|
||||
|
|
|
@ -85,21 +85,28 @@ int g1m_fopen(g1m_t **handle, const char *path, FILE *stream,
|
|||
g1m_type_t expected_type);
|
||||
#endif
|
||||
|
||||
/* open MCS head/file */
|
||||
/* 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,
|
||||
const unsigned char *dirname, const unsigned char *filename,
|
||||
uint_fast32_t filesize);
|
||||
int g1m_mcstype_correct(g1m_mcshead_t *head);
|
||||
|
||||
/* open and decode MCS file */
|
||||
int g1m_decode_mcsfile(g1m_mcsfile_t **handle,
|
||||
const g1m_mcshead_t *head, g1m_buffer_t *buffer);
|
||||
int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle,
|
||||
const g1m_mcshead_t *head, const unsigned char *data, size_t size);
|
||||
|
||||
/* open CAS head/file */
|
||||
/* open CAS head for decoding (TODO: correct it for encoding) */
|
||||
int g1m_decode_casfile_head(g1m_mcshead_t *head,
|
||||
const char *datatype, const char *filename, const char *specific);
|
||||
|
||||
/* open and decode CAS file */
|
||||
int g1m_decode_casfile(g1m_mcsfile_t **handle,
|
||||
const g1m_mcshead_t *head, g1m_buffer_t *buffer);
|
||||
int g1m_decode_casfile_data(g1m_mcsfile_t **handle,
|
||||
const g1m_mcshead_t *head, const unsigned char *data, size_t size);
|
||||
|
||||
/* free handles */
|
||||
void g1m_free(g1m_t *handle);
|
||||
|
|
|
@ -37,9 +37,20 @@ struct casemul_internal_header {
|
|||
uint32_t size;
|
||||
};
|
||||
|
||||
/* The multi-byte values are always little-endian, expected from the
|
||||
* values made with `MAKELONG` (like the internal header type, which, in the
|
||||
* source, is a DWORD), because its funnier. */
|
||||
/* The multi-byte values do not have a defined endianness! The Casemul files
|
||||
* are generated from C++ classes, so when one is generated, the host's
|
||||
* endianness is used. Also, there is no setting anywhere in the file to say
|
||||
* whether the host was big endian or little endian.
|
||||
*
|
||||
* Actually, there is a way to guess using the magic, which is made using
|
||||
* `MAKELONG`, which concatenates two words ('CA' and 'FS', 'AC' and 'SF' in
|
||||
* little endian). That means if it is "CASF", then the file was generated on
|
||||
* a big endian platform, and if it is "ACFS", it was generated on a little
|
||||
* endian platform.
|
||||
*
|
||||
* The libg1m implementation just supposes the file was generated on a
|
||||
* little-endian platform, as CasEmul was used when Microsoft Windows was
|
||||
* only implemented on x86-like platforms (little endian). */
|
||||
/* ************************************************************************** */
|
||||
/* Overall, source and compiled headers */
|
||||
/* ************************************************************************** */
|
||||
|
|
|
@ -37,8 +37,6 @@ int g1m_get_type_info(const char *path,
|
|||
/* get mcs type data */
|
||||
int g1m_mcstype_get(const char *groupname, const char *filename,
|
||||
unsigned int rawtype, unsigned int *type, int *id);
|
||||
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 *datatype, unsigned int *type);
|
||||
|
|
|
@ -71,7 +71,7 @@ typedef struct g1m_mcs_cell_s {
|
|||
/* Main structures */
|
||||
/* ************************************************************************** */
|
||||
/* mcs file head flags */
|
||||
# define g1m_mcshead_complex 0x0001 /* is a complex variable */
|
||||
# define g1m_mcsflag_complex 0x0001 /* is a complex variable */
|
||||
|
||||
/* mcs file head */
|
||||
typedef struct g1m_mcshead_s {
|
||||
|
@ -83,9 +83,12 @@ typedef struct g1m_mcshead_s {
|
|||
/* content size */
|
||||
uint_fast32_t size;
|
||||
|
||||
/* raw data */
|
||||
/* mcs-related raw data */
|
||||
unsigned int _rawtype;
|
||||
unsigned char _group[17], _dirname[9];
|
||||
|
||||
/* cas-related raw data */
|
||||
unsigned char _data[3];
|
||||
} g1m_mcshead_t;
|
||||
|
||||
/* mcs file */
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <libg1m/internals.h>
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Direct subfile decoding functions */
|
||||
/* Head decoding function */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* g1m_decode_casfile_head:
|
||||
|
@ -61,7 +61,11 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, const char *datatype,
|
|||
return (0);
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* File decoding functions */
|
||||
/* ************************************************************************** */
|
||||
/* TODO: g1m_decode_casfile */
|
||||
/* TODO: g1m_decode_casfile_data */
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* File decoding function */
|
||||
|
@ -92,6 +96,7 @@ int g1m_decode_cas(g1m_t *handle, g1m_buffer_t *buffer,
|
|||
(char*)hd.filename, (char*)hd._specific)))
|
||||
return (err);
|
||||
|
||||
/* TODO: decode it */
|
||||
/* everything went fine :) */
|
||||
return (0);
|
||||
return (g1m_error_wrong_type);
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
/* *****************************************************************************
|
||||
* decode/cat.c -- decode a CAT 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/>.
|
||||
*
|
||||
* CAT is a proprietary format by CASIO. It is a text-based format.
|
||||
* A description of it is available in the Casetta project documentation:
|
||||
* https://casetta.tuxfamily.org/formats/cat
|
||||
* ************************************************************************** */
|
||||
#include <libg1m/internals.h>
|
||||
|
||||
/* TODO */
|
|
@ -71,7 +71,7 @@ static mcs_decode_func_t lookup_mcsfile_decode(unsigned int type)
|
|||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Public file functions */
|
||||
/* Head decoding function */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* g1m_decode_mcsfile_head:
|
||||
|
@ -121,6 +121,9 @@ int g1m_decode_mcsfile_head(g1m_mcshead_t *head,
|
|||
return (0);
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* File decoding functions */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* g1m_decode_mcsfile:
|
||||
* Decode MCS file content.
|
||||
|
|
|
@ -71,12 +71,12 @@ static g1m_mcsfile_t *find_space_for_file(g1m_t *handle,
|
|||
found:;
|
||||
/* don't forget to copy basic things */
|
||||
g1m_mcsfile_t *file = *pfile;
|
||||
if (name) strncpy(file->head.name, name, 8);
|
||||
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_mcstype_toraw(type, id, file->head.name,
|
||||
(char*)file->head._dirname, (char*)file->head._group);
|
||||
g1m_mcstype_correct(&file->head);
|
||||
|
||||
/* return it */
|
||||
return (file);
|
||||
|
|
|
@ -21,23 +21,25 @@
|
|||
/* ************************************************************************** */
|
||||
/* Local types */
|
||||
/* ************************************************************************** */
|
||||
/* Type flags */
|
||||
#define noarg 0x0000
|
||||
#define arg 0x0001
|
||||
#define arg_is_num 0x0002
|
||||
#define arg_is_let 0x0000
|
||||
#define weight_by_gid 0x0004
|
||||
|
||||
/* Correspondance type */
|
||||
#define noarg 0
|
||||
#define arg 1
|
||||
#define arg_is_num 2
|
||||
#define arg_is_let 0
|
||||
#define weight_by_gid 4
|
||||
struct type_corresp {
|
||||
/* identification */
|
||||
unsigned int rawtype;
|
||||
const char *name; /* NULL: don't check */
|
||||
unsigned int flags;
|
||||
unsigned int flags; /* TODO: move */
|
||||
|
||||
/* information for logging and re-constituting information */
|
||||
const char *dirname;
|
||||
const char *info;
|
||||
|
||||
/* libg1m MCS file type */
|
||||
/* libg1m information */
|
||||
unsigned int type;
|
||||
};
|
||||
|
||||
|
@ -295,79 +297,79 @@ notfound:
|
|||
}
|
||||
|
||||
/**
|
||||
* g1m_mcstype_toraw:
|
||||
* Get raw information for writing.
|
||||
* g1m_mcstype_correct:
|
||||
* Correct information.
|
||||
*
|
||||
* @arg type the libg1m type.
|
||||
* @arg id the ID.
|
||||
* @arg name the name buffer.
|
||||
* @arg dirname the directory name buffer.
|
||||
* @arg groupname the groupname buffer.
|
||||
* @arg head the mcs head to correct.
|
||||
* @return if an error was encountered.
|
||||
*/
|
||||
|
||||
int g1m_mcstype_toraw(unsigned int type, int id,
|
||||
char *name, char *dirname, char *groupname)
|
||||
int g1m_mcstype_correct(g1m_mcshead_t *head)
|
||||
{
|
||||
/* check if there is a type */
|
||||
if (!head || !head->type)
|
||||
return (0);
|
||||
|
||||
/* find the group/type */
|
||||
struct group_corresp *g;
|
||||
struct type_corresp *t;
|
||||
for (g = mcs_groups; g->types; g++) for (t = g->types; t->dirname; t++) {
|
||||
/* check if the libg1m type corresponds */
|
||||
if (t->type != head->type) continue;
|
||||
|
||||
for (g = mcs_groups; g->types; g++) {
|
||||
for (t = g->types; t->dirname; t++) {
|
||||
/* check if the libg1m type corresponds */
|
||||
if (t->type != type)
|
||||
/* check if id is weighted by major */
|
||||
if (g1m_get_id_major(head->id)) {
|
||||
if (~t->flags & weight_by_gid)
|
||||
continue;
|
||||
/* check if id is weighted by major */
|
||||
if (g1m_get_id_major(id)) {
|
||||
if (~t->flags & weight_by_gid)
|
||||
continue;
|
||||
} else if (t->flags & weight_by_gid)
|
||||
continue;
|
||||
/* we found the entry! */
|
||||
goto found;
|
||||
}
|
||||
} else
|
||||
continue;
|
||||
|
||||
/* we have found the entry! */
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* not found */
|
||||
return (1);
|
||||
/* not found... */
|
||||
return (g1m_error_unknown);
|
||||
|
||||
found:
|
||||
found:;
|
||||
/* put the group name */
|
||||
strcpy(groupname, g->name);
|
||||
char *gr = (char*)head->_group;
|
||||
if (g->flags & arg) {
|
||||
int grid = g1m_get_id_major(id);
|
||||
int grid = g1m_get_id_major(head->id);
|
||||
if ((t->flags & arg) && ~t->flags & weight_by_gid)
|
||||
grid = g1m_get_id_minor(id);
|
||||
grid = g1m_get_id_minor(head->id);
|
||||
|
||||
if (grid == g1m_ans)
|
||||
sprintf(groupname, "%sAns", g->name);
|
||||
sprintf(gr, "%sAns", g->name);
|
||||
else if (grid == g1m_theta)
|
||||
sprintf(groupname, "%s\xCE", g->name);
|
||||
sprintf(gr, "%s\xCE", g->name);
|
||||
else if (grid == g1m_r)
|
||||
sprintf(groupname, "%s\xCD", g->name);
|
||||
sprintf(gr, "%s\xCD", g->name);
|
||||
else if (g->flags & arg_is_num)
|
||||
sprintf(groupname, "%s%d", g->name, grid);
|
||||
sprintf(gr, "%s%d", g->name, grid);
|
||||
else
|
||||
sprintf(groupname, "%s%c", g->name, grid + 'A' - 1);
|
||||
}
|
||||
sprintf(gr, "%s%c", g->name, grid + 'A' - 1);
|
||||
} else
|
||||
strcpy(gr, g->name);
|
||||
|
||||
/* put the directory name */
|
||||
strcpy(dirname, t->dirname);
|
||||
strcpy((char*)head->_dirname, t->dirname);
|
||||
|
||||
/* put the filename */
|
||||
char *nm = (char*)head->name;
|
||||
if (t->flags & arg) {
|
||||
int namid = g1m_get_id_minor(id);
|
||||
int namid = g1m_get_id_minor(head->id);
|
||||
|
||||
if (namid == g1m_ans)
|
||||
sprintf(name, "%sAns", t->name);
|
||||
sprintf(nm, "%sAns", t->name);
|
||||
else if (namid == g1m_theta)
|
||||
sprintf(name, "%s\xCE", t->name);
|
||||
sprintf(nm, "%s\xCE", t->name);
|
||||
else if (namid == g1m_r)
|
||||
sprintf(name, "%s\xCD", t->name);
|
||||
sprintf(nm, "%s\xCD", t->name);
|
||||
else if (t->flags & arg_is_num)
|
||||
sprintf(name, "%s%d", t->name, namid);
|
||||
sprintf(nm, "%s%d", t->name, namid);
|
||||
else
|
||||
sprintf(name, "%s%c", t->name, g1m_get_id_minor(id) + 'A' - 1);
|
||||
sprintf(nm, "%s%c", t->name, namid + 'A' - 1);
|
||||
}
|
||||
|
||||
/* no error */
|
||||
|
|
Reference in New Issue