cake
/
libg1m
Archived
1
0
Fork 0

Modified things.

This commit is contained in:
Thomas Touhey 2017-02-19 23:31:46 +01:00
parent 9ea6f8bf5b
commit 08b7995ad2
36 changed files with 690 additions and 1233 deletions

6
.gitmodules vendored
View File

@ -1,6 +0,0 @@
[submodule "tools/fontcharacter_reference"]
path = tools/fontcharacter_reference
url = https://github.com/cakeisalie5/fontcharacter_reference.git
[submodule "tools/.fontcharacter-root"]
path = tools/.fontcharacter-root
url = https://github.com/cakeisalie5/fontcharacter-python.git

View File

@ -57,7 +57,7 @@
ANAMES := lib$(NAME).lib lib$(NAME).a lib$(NAME).dll.a
# Required libs
LIBS := zlib
LIBS := zlib libfontcharacter
#******************************************************************************#
# Binary utilities #

View File

@ -25,9 +25,10 @@ I took these as a reference because these are the ones I work with.
| [python3](https://www.python.org/) | >= 3.5 |
### Runtime dependencies
| Name | Version |
| -------------------------------------------------- | -------- |
| [zlib](http://zlib.net/) | >= 1.2.8 |
| Name | Version |
| ------------------------------------------------------------------- | -------- |
| [zlib](http://zlib.net/) | >= 1.2.8 |
| [libfontcharacter](https://github.com/cakeisalie5/libfontcharacter) | >= 1.0 |
## Building
Just `./configure` then `make`.

7
configure vendored
View File

@ -18,6 +18,7 @@ more_warnings=
# Build options
target=
no_file=
static=
windows=
optimize_size=
@ -62,6 +63,7 @@ Build options:
--static build a static library (by default, dynamic)
--windows build DLLs and .libs instead of ELF and archives
--optimize-size optimize size instead of speed
--no-file do not use the libc FILE interface
--loglevel=LOGLEVEL library log level [$loglevel]
Installation options:
@ -125,6 +127,7 @@ for arg ; do case "$arg" in
--static) static=y ;;
--windows) windows=y ;;
--optimize-size) optimize_size=y ;;
--no-file) no_file=y ;;
--loglevel=*)
level="${arg#*=}"
# check if is in array
@ -213,8 +216,8 @@ fi
make mrproper MAKE_FULL_LOG=y 1>/dev/null 2>/dev/null
# Create the configuration header
opt=
# [no option yet.]
opt="--version=${version}"
[ "$no_file" ] && opt+=" --no-file"
tools/write-header-config $opt >include/libg1m/config.h
# Do it!

View File

@ -1,47 +0,0 @@
G1M_FCSTOMBS(3)
===============
Thomas "Cakeisalie5" Touhey
:Email: thomas@touhey.fr
:man source: libg1m
:man manual: libg1m manual
NAME
----
g1m_fcstombs - convert a FONTCHARACTER string to a multi-byte string
SYNOPSIS
--------
[source,c]
----
#include <libg1m.h>
size_t g1m_fcstombs(char *dst, const FONTCHARACTER *src, size_t n);
----
DESCRIPTION
-----------
Makes a multi-byte string out of a FONTCHARACTER string. If *dst* is *NULL*,
only the size will be calculated. Occupies max *n* character, terminating
zero included.
Will end the created string if *n > 0*. If a nul character is found in the
source string, it will be copied and won't be counted.
RETURN VALUE
------------
The size of the FONTCHARACTER string.
EXAMPLE
-------
[source,c]
----
size_t len = g1m_fcstombs(NULL, fcs, n);
char *s = malloc(len + 1);
if (!s)
return (malloc_pls);
g1m_fcstombs(s, fcs, n);
----
SEE ALSO
--------
*libg1m*(3), *g1m_mbstofcs*(3)

View File

@ -1,35 +0,0 @@
G1M_FCTOMB(3)
=============
Thomas "Cakeisalie5" Touhey
:Email: thomas@touhey.fr
:man source: libg1m
:man manual: libg1m manual
NAME
----
g1m_fctomb - FONTCHARACTER to multi-byte
SYNOPSIS
--------
[source,c]
----
#include <libg1m.h>
int g1m_fctomb(char *s, FONTCHARACTER fc);
----
DESCRIPTION
-----------
Convert a FONTCHARACTER character to its multibyte representation,
and stores it at the beginning of the character array pointed to by *s*.
The programmer must ensure that there is room for at least FC_MB_MAX bytes
at *s*.
RETURN VALUE
------------
This function returns the length of the calculated multibyte function.
SEE ALSO
--------
*libg1m*(3), *g1m_mbtofc*(3)

View File

@ -1,53 +0,0 @@
G1M_MBSTOFCS(3)
===============
Thomas "Cakeisalie5" Touhey
:Email: thomas@touhey.fr
:man source: libg1m
:man manual: libg1m manual
NAME
----
g1m_mbstofcs - convert a multi-byte string to a FONTCHARACTER string
SYNOPSIS
--------
[source,c]
----
#include <libg1m.h>
size_t g1m_mbstofcs(FONTCHARACTER *dest, const char *src, size_t n);
----
DESCRIPTION
-----------
Makes a FONTCHARACTER string out of a multi-byte string. If **dest* is *NULL*,
only the size will be calculated. *n* is the size of the destination buffer,
if it's zero, unlimited space is supposed (useful if you don't know the size
of the destination buffer you're going to allocate yet).
Will always end the destination buffer. If a nul character was found in the
source string, it will not be counted and copy/counting will stop there.
If an invalid multi-byte sequence is found, will simply act as if a nul
character was found in the source string.
RETURN VALUE
------------
The size of the calculated FONTCHARACTER string.
EXAMPLE
-------
[source,c]
----
size_t len = g1m_mbstofcs(NULL, src, 0);
if (len == (size_t)-1)
return (oops_i_did_it_again);
FONTCHARACTER *fcs = malloc(sizeof(FONTCHARACTER) * (len + 1));
if (!fcs)
return (malloc_me_baby_one_more_time);
g1m_mbstofcs(fcs, src, len + 1);
----
SEE ALSO
--------
*libg1m*(3), *g1m_fcstombs*(3)

View File

@ -1,33 +0,0 @@
G1M_MBTOFC(3)
=============
Thomas "Cakeisalie5" Touhey
:Email: thomas@touhey.fr
:man source: libg1m
:man manual: libg1m manual
NAME
----
g1m_mbtofc - convert a multi-byte sequence to a FONTCHARACTER char
SYNOPSIS
--------
[source,c]
----
#include <libg1m.h>
int g1m_mbtofc(FONTCHARACTER *pfc, const char *s, size_t n);
----
DESCRIPTION
-----------
Make a FONTCHARACTER out of a multi-byte sequence from **s*. *n* is the
maximum size of *s* (if zero, considered as *FC_MB_MAX*).
RETURN VALUE
------------
-1 if an incomplete multi-byte sequence was found, zero if the found character
was a terminating character, the size of the multi-byte sequence otherwise.
SEE ALSO
--------
*libg1m*(3), *g1m_fctomb*(3)

View File

@ -9,9 +9,11 @@
/* ************************************************************************** */
#ifndef LIBG1M_H
# define LIBG1M_H
# include <libg1m/config.h>
# include <libg1m/buffer.h>
# include <libg1m/bcd.h>
# include <libg1m/fontcharacter.h>
# include <libg1m/color.h>
# include <libfontcharacter.h>
# include <stdio.h>
# include <stdint.h>
# include <time.h>
@ -25,30 +27,27 @@ extern "C" {
/* ************************************************************************** */
/* Errors */
/* ************************************************************************** */
/* main enumeration */
typedef enum {
g1m_noerror,
/* WARNING: Whenever you add/remove errors, think about updating core/strerror!
* ---
* First, the none error. */
# define g1m_noerror 0x00
/* no stream sent -- if lib made the libc calls, check errno */
g1m_error_nostream,
/* could not read from stream */
g1m_error_noread,
/* could not seek in stream */
g1m_error_noseek,
/* Then, the miscallenous errors */
# define g1m_error_alloc 0x01
# define g1m_error_op 0x02
/* wrong type */
g1m_error_wrong_type,
/* Then, the stream errors */
# define g1m_error_nostream 0x10
# define g1m_error_noread 0x11
# define g1m_error_noseek 0x12
/* magic or control problem */
g1m_error_magic,
/* unexpected EOF */
g1m_error_eof,
/* memory allocation problem */
g1m_error_alloc,
/* Then, the decoding errors */
# define g1m_error_magic 0x20
# define g1m_error_eof 0x21
# define g1m_error_wrong_type 0x22
/* operation not supported for this type */
g1m_error_op,
} g1m_error_t;
/* Error type -- for compatibility with old programs using enum */
typedef int g1m_error_t;
/* Message getting macro */
extern const char *g1m_error_strings[];
@ -59,28 +58,30 @@ extern const char *g1m_error_strings[];
/* MCS-Related types */
/* ************************************************************************** */
/* BCD matrix - real and complex */
typedef struct {
struct bcd real;
struct bcd imgn;
typedef struct g1m_mcs_cell_s {
g1m_bcd_t real;
g1m_bcd_t imgn;
int used;
} g1m_mcs_cell_t;
/* MCS file type */
typedef unsigned int g1m_mcsfile_type_t;
# define g1m_mcstype_unknown 0x000
# define g1m_mcstype_program 0x001
# define g1m_mcstype_list 0x002
# define g1m_mcstype_mat 0x004
# define g1m_mcstype_pict 0x008
# define g1m_mcstype_capt 0x010
# define g1m_mcstype_spreadsheet 0x020
# define g1m_mcstype_string 0x040
# define g1m_mcstype_setup 0x080
# define g1m_mcstype_alphamem 0x100
# define g1m_mcstype_vct 0x200
/* MCS file type aliases */
# define g1m_mcstype_picture g1m_mcstype_pict
# define g1m_mcstype_capture g1m_mcstype_capt
# define g1m_mcstype_vector g1m_mcstype_vct
typedef enum {
g1m_mcstype_program = 0x01,
g1m_mcstype_list = 0x02,
g1m_mcstype_mat = 0x04,
g1m_mcstype_pict = 0x08,
g1m_mcstype_capt = 0x10,
g1m_mcstype_spreadsheet = 0x20,
g1m_mcstype_string = 0x40,
g1m_mcstype_setup = 0x80,
g1m_mcstype_alphamem = 0x100,
g1m_mcstype_vct = 0x200,
} g1m_mcsfile_type_t;
# define g1m_mcstype_vector g1m_mcstype_vct
/* uses id */
# define g1m_mcstype_uses_id(T) ((T) & (\
@ -90,9 +91,9 @@ typedef enum {
# define g1m_get_id_minor(I) ((I) & 31)
/* mcs file */
# define g1m_has_password(F) (F)->password[0]
# define g1m_has_password(F) (F)->password[0]
# define g1m_remove_password(F) (F)->password[0] = 0
typedef struct {
typedef struct g1m_mcsfile_s {
/* file type */
unsigned int type;
@ -125,25 +126,45 @@ typedef struct {
} g1m_mcsfile_t;
/* version */
typedef struct {
typedef struct g1m_version_s {
int major;
int minor;
int revision;
} g1m_version_t;
/* ************************************************************************** */
/* Storage files */
/* ************************************************************************** */
/* storage file type */
typedef unsigned int g1m_filetype_t;
# define g1m_filetype_directory 0x01
# define g1m_filetype_generic 0x02
/* storage file structure */
typedef struct g1m_file_s {
/* meta info */
unsigned int type;
struct g1m_file_s *parent;
int deleted;
/* content */
void *content;
} g1m_file_t;
/* ************************************************************************** */
/* E-activities related types */
/* ************************************************************************** */
/* line type */
# define g1m_linetype_pict g1m_linetype_picture
# define g1m_linetype_heading g1m_linetype_title
# define g1m_linetype_standard_heading g1m_linetype_title
typedef enum {
g1m_linetype_title = 0x01,
g1m_linetype_text = 0x02,
g1m_linetype_picture = 0x04,
g1m_linetype_eact = 0x08
} g1m_eact_line_type_t;
/* Line type */
typedef unsigned int g1m_eact_line_type_t;
# define g1m_linetype_title 0x01
# define g1m_linetype_text 0x02
# define g1m_linetype_picture 0x04
# define g1m_linetype_eact 0x08
/* Line type aliases */
# define g1m_linetype_pict g1m_linetype_picture
# define g1m_linetype_heading g1m_linetype_title
# define g1m_linetype_standard_heading g1m_linetype_title
/* line */
typedef struct g1m_line_s {
@ -164,27 +185,27 @@ typedef struct g1m_line_s {
/* ************************************************************************** */
/* General types */
/* ************************************************************************** */
/* type */
# define g1m_type_pict g1m_type_picture
# define g1m_type_eactivity g1m_type_eact
# define g1m_type_add_in g1m_type_addin
typedef enum {
g1m_type_addin = 0x01,
g1m_type_mcs = 0x02,
g1m_type_eact = 0x04,
g1m_type_pict = 0x08,
g1m_type_lang = 0x10,
g1m_type_fkey = 0x20,
g1m_type_storage = 0x40
} g1m_type_t;
/* General type */
typedef unsigned int g1m_type_t;
# define g1m_type_addin 0x01
# define g1m_type_mcs 0x02
# define g1m_type_eact 0x04
# define g1m_type_picture 0x08
# define g1m_type_lang 0x10
# define g1m_type_fkey 0x20
# define g1m_type_storage 0x40
/* platform */
typedef enum {
g1m_platform_none = 0x00,
g1m_platform_fx = 0x01,
g1m_platform_cp = 0x02,
g1m_platform_cg = 0x04
} g1m_platform_t;
/* General type aliases */
# define g1m_type_pict g1m_type_picture
# define g1m_type_eactivity g1m_type_eact
# define g1m_type_add_in g1m_type_addin
/* Platform */
typedef unsigned int g1m_platform_t;
# define g1m_platform_none 0x00
# define g1m_platform_fx 0x01
# define g1m_platform_cp 0x02
# define g1m_platform_cg 0x04
/* handle */
typedef struct {
@ -206,6 +227,9 @@ typedef struct {
/* MCS list */
g1m_mcsfile_t **files;
/* Storage files list */
g1m_file_t **sfiles;
/* Messages list */
char **messages;
@ -231,7 +255,7 @@ int g1m_fopen(g1m_t **handle, const char *path, FILE *stream,
g1m_type_t expected_type);
/* open MCS handle (this one is mainly for `libp7`) */
int g1m_parse_mcsfile_content(g1m_mcsfile_t **handle, FILE *stream,
int g1m_decode_mcsfile_content(g1m_mcsfile_t **handle, g1m_buffer_t *buffer,
int raw_type, const unsigned char *groupname,
const unsigned char *dirname, const unsigned char *filename,
uint_fast32_t filesize);

View File

@ -1,49 +0,0 @@
/* ************************************************************************** */
/* _____ _ */
/* libg1m/basic.h |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2017/01/07 17:00:25 |___/ */
/* */
/* ************************************************************************** */
#ifndef LIBG1M_BASIC_H
# define LIBG1M_BASIC_H
# define CBASIC_MAX_ARGUMENTS 3
/* libg1m has utilities for interacting with Basic programs!
* Everything is basically a statement, but when it's just a
* value/variable/..., it's instruction 0x00 with one argument.
*
* Here are the types an argument can take: */
enum g1m_argument_type {
g1m_argtype_value,
g1m_argtype_variable,
g1m_argtype_string,
g1m_argtype_list,
g1m_argtype_mat,
};
/* And here's the structure of a statement: */
typedef struct g1m_basic_statement_s {
FONTCHARACTER opcode;
int argtype, id;
/* BCD values */
struct bcd real;
struct bcd imgn;
/* arguments */
int nargs;
struct g1m_basic_statement_s *args;
} g1m_bst_t;
/* And here is the function to fetch an instruction from a program content
* buffer: */
int g1m_fetch_instruction(const FONTCHARACTER *buf, size_t size,
size_t *isize, g1m_bst_t *statement);
#endif /* LIBG1M_BASIC_H */

View File

@ -32,22 +32,22 @@ extern "C" {
*
* The other 15 digits are the mantissa. So the number is: (M ** (E + 1)) */
struct bcd {
typedef struct bcd {
/* the BCD value itself */
unsigned char BCDval[9];
/* some 4-bytes alignment stuff */
unsigned char _align[3];
};
} g1m_bcd_t;
/* ************************************************************************** */
/* BCD utilities */
/* ************************************************************************** */
/* Arithmetic */
int g1m_bcd_is_nonzero(struct bcd *bcd);
int g1m_bcd_is_nonzero(g1m_bcd_t *bcd);
/* String/BCD */
char *g1m_bcdtoa(struct bcd *bcd);
char *g1m_bcdtoa(g1m_bcd_t *bcd);
/* ************************************************************************** */
/* Inline BCD utilities */
@ -60,7 +60,7 @@ char *g1m_bcdtoa(struct bcd *bcd);
* @return a boolean.
*/
static inline int g1m_bcd_is_negative(struct bcd *bcd)
static inline int g1m_bcd_is_negative(g1m_bcd_t *bcd)
{
return (bcd->BCDval[0] >= 0x50);
}
@ -73,7 +73,7 @@ static inline int g1m_bcd_is_negative(struct bcd *bcd)
* @return a boolean.
*/
static inline int g1m_bcd_high_bit(struct bcd *bcd)
static inline int g1m_bcd_high_bit(g1m_bcd_t *bcd)
{
return (bcd->BCDval[0] & 0x80);
}

40
include/libg1m/buffer.h Normal file
View File

@ -0,0 +1,40 @@
/* ************************************************************************** */
/* _____ _ */
/* libg1m/buffer.h |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2017/02/12 16:04:33 |___/ */
/* */
/* ************************************************************************** */
#ifndef LIBG1M_BUFFER_H
# define LIBG1M_BUFFER_H
# include <stdlib.h>
# include <stdint.h>
/* This file is there so it is possible to use a custom buffer for file
* transferring. There are two use cases:
* - if you use a buffer to send data: the size of the element to send should
* be put in `size`, and the `read` function will be used;
* - if you use a buffer to receive data: if the `announce` function is set,
* it will be called with the size of the file to receive, in order to
* prepare space for the file. If the announce function returns an error,
* then the file will not be sent.
*
* Here are the used functions: */
typedef int (*g1m_buffer_read_t)(void*, unsigned char*, size_t);
typedef int (*g1m_buffer_write_t)(void*, const unsigned char*, size_t);
typedef int (*g1m_buffer_announce_t)(void*, uint_fast32_t size);
/* And here is the structure of a buffer: */
typedef struct {
void *cookie;
g1m_buffer_read_t read;
g1m_buffer_write_t write;
g1m_buffer_announce_t announce;
} g1m_buffer_t;
#endif /* LIBG1M_BUFFER_H */

View File

@ -18,21 +18,21 @@
*
* These colors are the following: */
typedef enum {
g1m_color_black = 0,
g1m_color_blue = 1,
g1m_color_green = 2,
g1m_color_cyan = 3,
g1m_color_red = 4,
g1m_color_magenta = 5,
g1m_color_yellow = 6,
g1m_color_white = 7
} g1m_color_t;
typedef int g1m_color_t;
# define g1m_color_black 0x0
# define g1m_color_blue 0x1
# define g1m_color_green 0x2
# define g1m_color_cyan 0x3
# define g1m_color_red 0x4
# define g1m_color_magenta 0x5
# define g1m_color_yellow 0x6
# define g1m_color_white 0x7
/* And here are some macros to help you out: */
# define g1m_marker_color(C) (((C) & 0xf0) >> 4)
# define g1m_char_color(C) ((C) & 0xf)
# define g1m_marker_color(C) (((C) & 0xf0) >> 4)
# define g1m_char_color(C) ((C) & 0xf)
# define g1m_character_color(C) g1m_char_color(C)
#endif /* LIBG1M_COLOR_H */

View File

@ -1,43 +0,0 @@
/* ************************************************************************** */
/* _____ _ */
/* libg1m/fontcharacter.h |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/11/21 09:26:47 |___/ */
/* */
/* ************************************************************************** */
#ifndef LIBG1M_FONTCHARACTER_H
# define LIBG1M_FONTCHARACTER_H
# include <stdlib.h>
# include <stdint.h>
# define FC_MB_MAX 2
# ifdef __cplusplus
extern "C" {
# endif
/* ************************************************************************** */
/* Main type */
/* ************************************************************************** */
/* CASIO's character encoding, named `FONTCHARACTER` by its SDK, is a simple
* multibyte one : if the character is a special one, then the next one is
* to read.
*
* Special characters are: 0x7F, 0xF7, 0xF9, 0xE5, 0xE6, 0xE7. */
typedef uint16_t FONTCHARACTER;
/* ************************************************************************** */
/* Utilities */
/* ************************************************************************** */
/* encoding characters */
int g1m_mbtofc(FONTCHARACTER *pfc, const char *s, size_t n);
int g1m_fctomb(char *s, FONTCHARACTER fc);
/* encoding strings */
size_t g1m_mbstofcs(FONTCHARACTER *dst, const char *src, size_t n);
size_t g1m_fcstombs(char *dst, const FONTCHARACTER *src, size_t n);
# ifdef __cplusplus
}
# endif
#endif /* LIBG1M_FONTCHARACTER_H */

View File

@ -70,7 +70,9 @@ struct standard_header {
* We also thought the subtype was only one-byte long, but the C2P came along
* with its "c2p\0\0\0" subtype.
*
* All main ID/types correspondances are in the `src/utils/type.c` file. */
* All main ID/types correspondances are in the `src/utils/type.c` file.
* From a user program, you can use the functions
* in `include/libg1m/formatutils.h`. */
# pragma pack()

View File

@ -32,8 +32,11 @@ struct storage_entry {
/* the type number - see below */
uint16_t type;
/* the unique number of the entry */
uint16_t uuid;
/* the number of the entry
* if this field is 0x00, just ignore the entry.
* we don't know why entries with this field set to 0x00 exist...
* (probably backups?) */
uint16_t id;
/* the raw subheader */
uint8_t raw_subheader[28];
@ -50,26 +53,46 @@ enum storage_entry_type {
storage_entrytype_fragment = 0x130,
};
/* The list has 0x800 entries, and occupies the two first sectors (or maybe
* just one, but it looks like data storage starts at sector 3). Entries with
* a type being 0xFFFF should not be read. */
/* The special nibble is usually zero when deleted, and non-zero when active.
* According to Simon Lothar, this is because it is possible to clear bits
* on the flash by flashwriting a short value only; but when it comes to
* set bits, it becomes more tricky.
*
* This is also why optimizing is not done straight away (to save the flash
* a little).
*
* The list can have to 0x800 entries, and occupies the first sector.
* Simon Lothar says the list can expand to the second sector (which is used
* only if there is no space in the index sector or the other data sectors).
* Entries with the 0xFFFF type should not be read.
*
* Some entry types can have parents. In this case, they have parent type,
* and parent number fields. This is because elements with different types
* follow different numerations; so the type field is here on which numeration
* to search for the member. If the parent type is 0xFFFF (or -1, as some say),
* then there is no parent.
*
* For now, only directories as parents for files have been encountered. */
/* ************************************************************************** */
/* Sectors */
/* ************************************************************************** */
/* Sectors represent the physical sectors of the storage memory (space!).
* Simon Lothar says that there are 27 entries for them (or 25 "not on the
* AU" in the other documentation, whatever that means). If the logical number
* is 0xFFFFFFFF, the sector is unused. First sector contains gibberish in the
* logical number field, as it's occupied by the directory.
* They are 64 KiB large.
*
* Their special nibble is either 0x04 or 0x00, I don't know why yet.
* Here is their subheader structure: */
* Simon Lothar says that there are 27 entries for them (or 14 on the AU models
* because of australian exam regulations). If the logical number
* is 0xFFFFFFFF, the sector is unused. (sometimes the logical number field
* contains gibberish, I don't know why yet)
*
* Their special nibble is either 0x04 or 0x00, the signification of it is not
* known to me yet. Here is their subheader structure: */
struct storage_sector {
/* the sector start address - 0xFF */
uint32_t startaddr;
/* the sector ID - because for some reason, fragments won't use the uuid */
/* the sector ID - probably not using the UUID so sectors can
* not be set as parent nodes :) */
uint32_t logical_sector_number;
};
@ -82,8 +105,9 @@ struct storage_sector {
* Here is their subheader structure: */
struct storage_directory {
/* the directory reference - looks unusable */
uint32_t directory_reference;
/* the parent type and id */
uint16_t parent_type;
uint16_t parent_id;
/* the name (FONTCHARACTER-encoded) */
FONTCHARACTER name[12];
@ -98,13 +122,9 @@ struct storage_directory {
* Here is their subheader structure: */
struct storage_file {
/* the directory reference
* - is `storage_entrytype_directory` if the file is in a subdirectory.
* - is 0xFFFF otherwise. */
uint16_t directory_reference;
/* the directory number - should be read only if is in a subdirectory. */
uint16_t directory_number;
/* the parent type and id (not functional?) */
uint16_t parent_type;
uint16_t parent_id;
/* the name (FONTCHARACTER-encoded) */
FONTCHARACTER name[12];
@ -117,36 +137,40 @@ struct storage_file {
* Fragments are in fact links to the sectors, with some more info.
*
* Their special nibble have the same meaning that for files... but are not
* always accurate, so only check on files.
* Here is their subheader structure: */
* always accurate, so only check on files!
*
* The first fragment corresponding to a file contain this file's type,
* probably detected when the file is transferred. Here are the
* known values: */
enum storage_file_type {
g1m_storage_filetype_unknown = 0x01,
g1m_storage_filetype_addin = 0x02, /* G1A */
g1m_storage_filetype_mcs = 0x06, /* G1M */
g1m_storage_filetype_g2r = 0x2E, /* G1R */
};
/* Why is the file type here and not in the file header? I don't know.
* And here is the fragments' subheader structure: */
struct storage_fragment {
/* the file ID */
uint32_t file_uuid;
/* the parent (file node) type and id */
uint16_t parent_type;
uint16_t parent_id;
/* the file type (probably detected when the file is transferred):
* - 0x01 for an unknown type;
* - 0x02 for an add-in (G1A);
* - 0x06 for an MCS archive (G1M);
* - 0x2E for an MCS archive with setup (G1R).
*
* why is it here and not in the file entry data? you've got a point. */
/* the file type */
uint16_t file_type;
/* the fragment count */
/* the fragment count and id */
uint16_t fragment_count;
/* the fragment number */
uint16_t fragment_id;
/* the sector id that the fragment is linked to */
uint16_t fragment_sector_id;
/* offset of the used bytes in sector */
uint16_t used_bytes_offset;
/* number of used bytes in sector */
uint16_t used_bytes;
/* number and offset in the sector of the fragment's bytes */
uint16_t data_offset;
uint16_t data_length;
};
#endif /* LIBG1M_FORMAT_STORAGE_H */

View File

@ -42,22 +42,12 @@
/* ************************************************************************** */
/* read with EOF check */
#define READ(TO, SZ) { \
size_t READ_size = fread(TO, 1, SZ, stream); \
if (!READ_size) { \
log_error("READING failed: read %" PRIuSIZE "/%" PRIuSIZE \
" bytes, %" PRIuSIZE " missing.", READ_size, SZ, \
(SZ) - READ_size); \
return (g1m_error_eof); \
}}
#define GREAD(TO, SZ) { \
size_t READ_size = fread(TO, 1, SZ, stream); \
if (!READ_size) { \
log_error("READING failed: read %" PRIuSIZE "/%" PRIuSIZE \
" bytes, %" PRIuSIZE " missing.", READ_size, SZ, \
(SZ) - READ_size); \
err = g1m_error_eof; \
goto fail; \
}}
int READ_err = (*buffer->read)(buffer->cookie, (void*)(TO), (SZ)); \
if (READ_err) return (READ_err); \
}
#define GREAD(TO, SZ) \
if ((err = (*buffer->read)(buffer->cookie, (void*)(TO), (SZ)))) \
goto fail;
/* read with EOF check, declare var before */
#define DREAD(NAM, STRUCT) \
struct STRUCT NAM; \
@ -66,36 +56,31 @@
struct STRUCT NAM; \
GREAD(&NAM, sizeof(struct STRUCT))
/* skip */
#define SKIP(SZ) \
if (g1m_parse_skip(stream, SZ, NULL)) return (g1m_error_eof);
#define SKIP(SZ) { \
int SKIP_err = g1m_skip(buffer, SZ, NULL); \
if (SKIP_err) return (SKIP_err); \
}
/* ************************************************************************** */
/* Specific parsing functions */
/* ************************************************************************** */
typedef int (g1m_decode_function)(g1m_t*, g1m_buffer_t*,
struct standard_header*);
/* types */
int g1m_parse_g3p(g1m_t *handle, FILE *stream,
struct standard_header *std);
int g1m_parse_c2p(g1m_t *handle, FILE *stream,
struct standard_header *std);
int g1m_parse_mcs(g1m_t *handle, FILE *stream,
struct standard_header *std);
int g1m_parse_eact(g1m_t * handle, FILE *stream,
struct standard_header *std);
int g1m_parse_addin(g1m_t *handle, FILE *stream,
struct standard_header *std);
int g1m_parse_addin_cg(g1m_t *handle, FILE *stream,
struct standard_header *std);
int g1m_parse_lang(g1m_t *handle, FILE *stream,
struct standard_header *std);
int g1m_parse_lang_cg(g1m_t *handle, FILE *stream,
struct standard_header *std);
int g1m_parse_fkey(g1m_t *handle, FILE *stream,
struct standard_header *std);
int g1m_parse_storage(g1m_t *handle, FILE *stream,
struct standard_header *std);
g1m_decode_function g1m_decode_g3p;
g1m_decode_function g1m_decode_c2p;
g1m_decode_function g1m_decode_mcs;
g1m_decode_function g1m_decode_eact;
g1m_decode_function g1m_decode_addin;
g1m_decode_function g1m_decode_addin_cg;
g1m_decode_function g1m_decode_lang;
g1m_decode_function g1m_decode_lang_cg;
g1m_decode_function g1m_decode_fkey;
g1m_decode_function g1m_decode_storage;
/* others */
int g1m_parse_fkey_cg_content(g1m_t *handle, FILE *stream,
int g1m_decode_fkey_cg_content(g1m_t *handle, g1m_buffer_t *buffer,
uint_fast32_t zonesize, uint32_t *pchecksum);
/* ************************************************************************** */
@ -125,7 +110,7 @@ G1M_PROTOTYPE_PIX(16bits)
/* Utilities */
/* ************************************************************************** */
/* Parsing */
int g1m_parse(g1m_t *handle, const char *path, FILE *stream,
int g1m_decode(g1m_t *handle, const char *path, g1m_buffer_t *buffer,
g1m_type_t expected_type);
/* Making */
@ -138,9 +123,12 @@ void g1m_free_mcs(g1m_t *handle);
void g1m_free_line_content(g1m_line_t *line);
/* Skipping */
int g1m_parse_skip(FILE *stream, size_t size, uint_fast32_t *checksum);
int g1m_skip(g1m_buffer_t *buffer, size_t size, uint_fast32_t *checksum);
/* Checksum-ing */
uint32_t g1m_checksum32(void *mem, size_t size, uint32_t checksum);
/* File buffer */
int g1m_filebuffer_read(void *vcookie, unsigned char *buf, size_t size);
#endif /* LIBG1M_INTERNALS_H */

View File

@ -1,232 +0,0 @@
/* ************************************************************************** */
/* _____ _ */
/* basic/instruction.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2017/01/07 14:55:53 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
#define go_forward(N) *buf += (N); *size -= (N)
/* ************************************************************************** */
/* Utilities */
/* ************************************************************************** */
/**
* parse_bcd:
* Parse a BCD.
*
* @arg buf the FONTCHARACTER buffer.
* @arg size the buffer size.
* @arg real the real part.
* @arg imgn the imaginary part.
* @return the error.
*/
static int fetch_bcd(const FONTCHARACTER **buf, size_t *size,
struct bcd *real, struct bcd *imgn)
{
/* TODO */
return (g1m_error_eof);
}
/**
* fetch_int:
* Decode an integer.
*
* @arg buf the FONTCHARACTER buffer.
* @arg size the buffer size.
* @arg num the integer to parse.
*/
static int fetch_int(const FONTCHARACTER **buf, size_t *size, int *id)
{
/* check the ans */
if (**buf == 0xC0) { *id = g1m_ans; (*buf)++; (*size)--; return (0); }
/* peek and get the size of the number */
int i; for (i = 0; i < *size && (*buf)[i] >= '0' && (*buf)[i] <= '9'; i++);
/* get the number */
int numsize = i;
*id = 0; while (i-- >= 0) *id = *id * 10 + (*buf)[i] - '0';
/* go forward and ok */
go_forward(numsize);
return (0);
}
/**
* fetch_argument:
* Decode an argument.
*
* @arg buf the FONTCHARACTER buffer.
* @arg size the buffer size.
* @arg arg the argument structure.
* @return if there was an error
*/
#define VAR(ID) (struct argument){.type = g1m_argtype_var, .id = (ID)}
static int fetch_argument(const FONTCHARACTER **buf, size_t *size,
struct argument *arg)
{
/* check if we have at least one character */
if (!*size) return (g1m_error_eof);
/* check if is something special */
FONTCHARACTER op = **buf;
if (opcode == 0xF93F) { arg->type = g1m_argtype_string; goto parse_id; }
if (opcode == 0x7F40) { arg->type = g1m_argtype_mat; goto parse_let; }
if (opcode == 0x7F51) { arg->type = g1m_argtype_list; goto parse_id; }
/* check if it's a var */
if (op == 0xC0) *arg = VAR(g1m_ans);
else if (op == 0xCE) *arg = VAR(g1m_theta);
else if (op == 0xCD) *arg = VAR(g1m_r);
else if (op >= 'A' && op <= 'Z') *arg = VAR(op - 'A');
else {
int err = fetch_bcd(buf, size, &arg->real, &arg->imgn);
if (err) return (fetch_statement(buf, size, arg->statement));
return (err);
}
/* was a var */
go_forward(1);
return (0);
/* it's something with an ID! */
parse_id:
go_forward(1);
return (fetch_int(buf, size, &arg->id));
/* it's something with a letter ID! */
parse_let:
go_forward(1);
return (fetch_let(buf, size, &arg->id));
}
/* ************************************************************************** */
/* Statements */
/* ************************************************************************** */
/* Statements */
struct statement {
/* the start opcode */
FONTCHARACTER opcode;
/* number of arguments */
int nargs;
/* finishes with a parenthesis */
int par;
};
/* Known statements */
static const struct statement statements[] = {
/* Locate x,x,x */
{0xF710, 3, 0},
/* Send(A) */
{0xF711, 1, 1},
/* Receive(A) */
{0xF712, 1, 1},
{0, 0}
};
/* Infix statements */
static const struct statement infix_statements[] = {
/* x! */
{0xEA, 1, 0},
/* a = b */
{0x3D, 2, 0},
{0, 0}
};
/**
* fetch_raw_statement:
* Fetch a statement.
*
* @arg buf the FONTCHARACTER buffer pointer.
* @arg size the FONTCHARACTER buffer size pointer.
* @arg st the statement pointer.
* @arg fst the first argument
* @arg infix is infix (boolean!)
* @return the error.
*/
static int fetch_raw_statement(const FONTCHARACTER **buf, size_t *size,
struct statement *st, struct argument *fst, int infix)
{
/* check if there is at least space for one opcode */
if (!*size) return (1);
/* get the statements tab */
const struct *sts =
(const *struct statement[]){statements, infix_statements}[infix];
/* check which opcode it is */
FONTCHARACTER op = **buf;
const struct *st;
for (st = sts; st->opcode && st->opcode != op; st++);
if (!st) return (1);
/* prepare the arguments */
int nargs = st->nargs;
struct argument *args = malloc(nargs * sizeof(struct argument));
if (!args) return (1);
if (nargs) memcpy(&args[0], fst, sizeof(struct argument));
/* iterate */
int last = infix - 1;
for (int i = infix; i < nargs; i++) {
/* parse the arg */
if (fetch_argument(buf, size, &args[i]))
return (1);
/* check the comma */
if (i < last && (!*size || **buf != ','))
return (1);
go_forward(1);
}
/* check right parenthesis */
if (st->par && *size && **buf != ')')
return (1);
if (*size) { go_forward(1); }
/* no error */
return (0);
}
/**
* fetch_statement:
* Fetch a statement.
*/
/* ************************************************************************** */
/* Main function */
/* ************************************************************************** */
/**
* g1m_fetch_instruction:
* Fetch the instruction.
*
* @arg buf the FONTCHARACTER buffer.
* @arg size the FONTCHARACTER buffer size.
* @arg statement the statement.
* @return if negative: the negative libg1m error code.
* otherwise: the size of the instruction.
*/
int g1m_fetch_instruction(const FONTCHARACTER *buf, size_t size,
g1m_bst_t *statement)
{
size_t sav = size;
/* start by free-ing statement content? */
/* TODO */
/* check it it's a statement */
int err = fetch_statement(&buf, &size, &statement, 0);
return (err ? -err : (int)(sav - size));
}

View File

@ -1,10 +1,10 @@
/* ************************************************************************** */
/* _____ _ */
/* parse/addin.c |_ _|__ _ _| |__ ___ _ _ */
/* decode/addin.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/12/01 13:33:45 |___/ */
/* Last updated: 2017/02/19 23:01:18 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
@ -65,18 +65,20 @@ static void addin_set_data(g1m_t *handle,
}
/**
* g1m_parse_addin:
* Parse "normal" add-in (after Standard Header).
* g1m_decode_addin:
* Decodes a "normal" add-in (after Standard Header).
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @return the error code (0 if ok).
*/
int g1m_parse_addin(g1m_t *handle, FILE *stream,
int g1m_decode_addin(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
int err = 0;
(void)std;
/* get the subheader */
DREAD(hd, g1a_subheader)
@ -112,20 +114,20 @@ int g1m_parse_addin(g1m_t *handle, FILE *stream,
- sizeof(struct g1a_subheader))
/* no errors */
return (0);
return (err);
}
/**
* g1m_parse_addin_cg:
* Parse fx-CG add-in (after Standard Header).
* g1m_decode_addin_cg:
* Decode fx-CG add-in (after Standard Header).
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg std the standard header.
* @return the error code (0 if ok).
*/
int g1m_parse_addin_cg(g1m_t *handle, FILE *stream,
int g1m_decode_addin_cg(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
int err = 0;
@ -179,7 +181,7 @@ int g1m_parse_addin_cg(g1m_t *handle, FILE *stream,
}
/* skip content for now */
if ((err = g1m_parse_skip(stream, content_size, &checksum)))
if ((err = g1m_skip(buffer, content_size, &checksum)))
goto fail;
/* check the sum (yo!) */

View File

@ -1,6 +1,15 @@
/* ************************************************************************** */
/* _____ _ */
/* parse/eact.c |_ _|__ _ _| |__ ___ _ _ */
/* decode/eact.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2017/02/19 23:01:18 |___/ */
/* */
/* ************************************************************************** */
/* ************************************************************************** */
/* _____ _ */
/* decode/eact.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
@ -13,12 +22,12 @@
/* Content parsing */
/* ************************************************************************** */
/* line content parsing function prototype */
static int eact_parse_line(g1m_line_t *handle, uint8_t *buf, size_t size,
static int eact_decode_line(g1m_line_t *handle, uint8_t *buf, size_t size,
uint_fast8_t type);
/**
* eact_parse_content_eact:
* Parse an EACT in an EACT, from the subheader.
* eact_decode_content_eact:
* Decodes an EACT in an EACT, from the subheader.
*
* @arg handle the handle.
* @arg buf the buffer.
@ -26,7 +35,7 @@ static int eact_parse_line(g1m_line_t *handle, uint8_t *buf, size_t size,
* @return the error code (0 if ok).
*/
static int eact_parse_content_eact(g1m_line_t *handle, uint8_t *buf,
static int eact_decode_content_eact(g1m_line_t *handle, uint8_t *buf,
size_t bufsize)
{
int err;
@ -100,7 +109,7 @@ static int eact_parse_content_eact(g1m_line_t *handle, uint8_t *buf,
goto loop_fail;
/* look for the line type */
err = eact_parse_line(line, &buf[entry_offset], linesize, entry_type);
err = eact_decode_line(line, &buf[entry_offset], linesize, entry_type);
if (err) goto loop_fail;
/* store and continue */
@ -127,12 +136,12 @@ fail:
struct eact_content_type_corresp {
const char *type;
int (*parse)(g1m_line_t*, uint8_t*, size_t);
int (*decode)(g1m_line_t*, uint8_t*, size_t);
};
/* Correspondance list */
static struct eact_content_type_corresp eact_content_types[] = {
{"@EACT\0\0", eact_parse_content_eact},
{"@EACT\0\0", eact_decode_content_eact},
{}
};
@ -140,8 +149,8 @@ static struct eact_content_type_corresp eact_content_types[] = {
/* Line parsing */
/* ************************************************************************** */
/**
* eact_parse_line_content:
* Parse an E-Activity content.
* eact_decode_line_content:
* Decodes an E-Activity content.
*
* @arg handle the handle.
* @arg buf the buffer.
@ -149,7 +158,7 @@ static struct eact_content_type_corresp eact_content_types[] = {
* @return the error code (0 if ok).
*/
static int eact_parse_line_content(g1m_line_t *handle, uint8_t *buf,
static int eact_decode_line_content(g1m_line_t *handle, uint8_t *buf,
size_t size)
{
/* read content header */
@ -173,19 +182,19 @@ static int eact_parse_line_content(g1m_line_t *handle, uint8_t *buf,
/* check for content type */
struct eact_content_type_corresp *ctype = eact_content_types;
while (ctype->parse) {
while (ctype->decode) {
if (!memcmp(hd.type, ctype->type, 8))
break ;
ctype++;
}
if (!ctype->parse) {
if (!ctype->decode) {
log_error("Unknown content type: '%.8s'", hd.type);
return (0);
}
/* then parse */
/* then decode */
int err;
if ((err = (*ctype->parse)(handle, buf, size)))
if ((err = (*ctype->decode)(handle, buf, size)))
return (err);
/* otherwise, no error. */
@ -193,8 +202,8 @@ static int eact_parse_line_content(g1m_line_t *handle, uint8_t *buf,
}
/**
* eact_parse_line_calculation:
* Parse a calculation.
* eact_decode_line_calculation:
* Decodes a calculation.
*
* @arg handle the handle.
* @arg buf the buffer.
@ -202,7 +211,7 @@ static int eact_parse_line_content(g1m_line_t *handle, uint8_t *buf,
* @return the error code (0 if ok).
*/
static int eact_parse_line_calculation(g1m_line_t *handle, uint8_t *buf,
static int eact_decode_line_calculation(g1m_line_t *handle, uint8_t *buf,
size_t size)
{
(void)handle;
@ -215,8 +224,8 @@ static int eact_parse_line_calculation(g1m_line_t *handle, uint8_t *buf,
}
/**
* eact_parse_line_result:
* Parse a calculation result.
* eact_decode_line_result:
* Decodes a calculation result.
*
* @arg handle the handle.
* @arg buf the buffer.
@ -224,7 +233,7 @@ static int eact_parse_line_calculation(g1m_line_t *handle, uint8_t *buf,
* @return the error code (0 if ok).
*/
static int eact_parse_line_result(g1m_line_t *handle, uint8_t *buf, size_t size)
static int eact_decode_line_result(g1m_line_t *handle, uint8_t *buf, size_t size)
{
(void)handle;
(void)buf;
@ -236,8 +245,8 @@ static int eact_parse_line_result(g1m_line_t *handle, uint8_t *buf, size_t size)
}
/**
* eact_parse_line_stdheading:
* Parse standard heading line.
* eact_decode_line_stdheading:
* Decodes standard heading line.
*
* @arg handle the handle.
* @arg buf the buffer.
@ -245,7 +254,7 @@ static int eact_parse_line_result(g1m_line_t *handle, uint8_t *buf, size_t size)
* @return the error code (0 if ok).
*/
static int eact_parse_line_stdheading(g1m_line_t *handle, uint8_t *buf,
static int eact_decode_line_stdheading(g1m_line_t *handle, uint8_t *buf,
size_t size)
{
/* log */
@ -262,8 +271,8 @@ static int eact_parse_line_stdheading(g1m_line_t *handle, uint8_t *buf,
}
/**
* eact_parse_line_picture:
* Parse picture line.
* eact_decode_line_picture:
* Decodes picture line.
*
* @arg handle the handle.
* @arg buf the buffer.
@ -271,7 +280,7 @@ static int eact_parse_line_stdheading(g1m_line_t *handle, uint8_t *buf,
* @return the error code (0 if ok).
*/
static int eact_parse_line_picture(g1m_line_t *handle, uint8_t *buf,
static int eact_decode_line_picture(g1m_line_t *handle, uint8_t *buf,
size_t size)
{
/* log */
@ -284,13 +293,13 @@ static int eact_parse_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 = g1m_fcstombs(NULL, s, 0);
size_t sz = fc_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);
g1m_fcstombs(handle->content, s, 0);
fc_wcstombs(handle->content, s, 0);
/* don't forget to set the handle type! */
handle->type = g1m_linetype_picture;
@ -300,8 +309,8 @@ static int eact_parse_line_picture(g1m_line_t *handle, uint8_t *buf,
}
/**
* eact_parse_line_text:
* Parse text line.
* eact_decode_line_text:
* Decodes a text line.
*
* @arg handle the handle.
* @arg buf the buffer.
@ -309,7 +318,7 @@ static int eact_parse_line_picture(g1m_line_t *handle, uint8_t *buf,
* @return the error code (0 if ok).
*/
static int eact_parse_line_text(g1m_line_t *handle, uint8_t *buf, size_t size)
static int eact_decode_line_text(g1m_line_t *handle, uint8_t *buf, size_t size)
{
/* log */
log_info("Text raw data is:");
@ -326,8 +335,8 @@ static int eact_parse_line_text(g1m_line_t *handle, uint8_t *buf, size_t size)
}
/**
* eact_parse_line_code:
* Parse code line.
* eact_decode_line_code:
* Decodes code line.
*
* @arg handle the handle.
* @arg buf the buffer.
@ -335,7 +344,7 @@ static int eact_parse_line_text(g1m_line_t *handle, uint8_t *buf, size_t size)
* @return the error code (0 if ok).
*/
static int eact_parse_line_code(g1m_line_t *handle, uint8_t *buf, size_t size)
static int eact_decode_line_code(g1m_line_t *handle, uint8_t *buf, size_t size)
{
(void)handle;
(void)buf;
@ -353,32 +362,32 @@ static int eact_parse_line_code(g1m_line_t *handle, uint8_t *buf, size_t size)
struct eact_line_type_corresp {
int rawtype;
int (*parse)(g1m_line_t*, uint8_t*, size_t);
int (*decode)(g1m_line_t*, uint8_t*, size_t);
const char *info;
};
/* All correspondances */
static struct eact_line_type_corresp eact_line_types[] = {
{eact_ltype_calc, eact_parse_line_calculation,
{eact_ltype_calc, eact_decode_line_calculation,
"calculation"},
{eact_ltype_calc_result, eact_parse_line_result,
{eact_ltype_calc_result, eact_decode_line_result,
"calculation result"},
{eact_ltype_content, eact_parse_line_content,
{eact_ltype_content, eact_decode_line_content,
"content"},
{eact_ltype_stdheading, eact_parse_line_stdheading,
{eact_ltype_stdheading, eact_decode_line_stdheading,
"standard heading"},
{eact_ltype_picture, eact_parse_line_picture,
{eact_ltype_picture, eact_decode_line_picture,
"picture"},
{eact_ltype_text, eact_parse_line_text,
{eact_ltype_text, eact_decode_line_text,
"pure text"},
{eact_ltype_code, eact_parse_line_code,
{eact_ltype_code, eact_decode_line_code,
"text mixed with functions"},
{}
};
/**
* eact_parse_line:
* Parse a line [content].
* eact_decode_line:
* decode a line [content].
*
* @arg handle the handle.
* @arg buf the buffer.
@ -387,7 +396,7 @@ static struct eact_line_type_corresp eact_line_types[] = {
* @return the error code (0 if ok).
*/
static int eact_parse_line(g1m_line_t *handle, uint8_t *buf, size_t size,
static int eact_decode_line(g1m_line_t *handle, uint8_t *buf, size_t size,
uint_fast8_t type)
{
/* initialize handle */
@ -395,40 +404,40 @@ static int eact_parse_line(g1m_line_t *handle, uint8_t *buf, size_t size,
/* look for the line type */
struct eact_line_type_corresp *linetype = eact_line_types;
while (linetype->parse) {
while (linetype->decode) {
if (linetype->rawtype == type)
break;
linetype++;
}
if (!linetype->parse) {
if (!linetype->decode) {
log_error("unknown line type: %02x", type);
return (0);
}
/* act */
log_info("line type is '%s' (0x%02x)", linetype->info, type);
return ((*linetype->parse)(handle, buf, size));
return ((*linetype->decode)(handle, buf, size));
}
/* ************************************************************************** */
/* Main parsing functions */
/* ************************************************************************** */
/**
* g1m_parse_eact:
* Parse an EACT.
* g1m_decode_eact:
* Decodes an EACT.
*
* Thanks to Julese50 for his help on e-acts parsing.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @return the error code (0 if ok).
*/
int g1m_parse_eact(g1m_t * handle, FILE *stream,
int g1m_decode_eact(g1m_t * handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
(void)std;
/* parse the header */
/* decode the header */
DREAD(hd, eact_header)
/* correct endianess */
@ -460,6 +469,6 @@ int g1m_parse_eact(g1m_t * handle, FILE *stream,
/* prepare handle */
handle->line = &handle->_linedata;
/* parse content */
return (eact_parse_line_content(handle->line, buf, bufsize));
/* decode content */
return (eact_decode_line_content(handle->line, buf, bufsize));
}

View File

@ -1,10 +1,10 @@
/* ************************************************************************** */
/* _____ _ */
/* parse/fkey.c |_ _|__ _ _| |__ ___ _ _ */
/* decode/fkey.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/12/17 00:21:32 |___/ */
/* Last updated: 2017/02/19 23:01:18 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
@ -52,16 +52,16 @@ static uint32_t **fkeydup3(uint8_t *fkey)
/* fx function keys file parsing utilities */
/* ************************************************************************** */
/**
* g1m_parse_fkey:
* Parse fx function keys files.
* g1m_decode_fkey:
* Decode fx function keys files.
*
* @arg handle the libg1m handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg std pointer to the standard header.
* @return the error code (0 if ok).
*/
int g1m_parse_fkey(g1m_t *handle, FILE *stream,
int g1m_decode_fkey(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
(void)std;
@ -125,23 +125,23 @@ fail:
/* cg function keys file parsing utilities */
/* ************************************************************************** */
/**
* g1m_parse_fkey_cg_content:
* Parse fx-CG key files.
* g1m_decode_fkey_cg_content:
* Decode fx-CG key files.
*
* In fact, the main parsing function is `g1m_parse_lang_cg` (they really
* In fact, the main parsing function is `g1m_decode_lang_cg` (they really
* have the same subheader). TODO
*
* @arg handle the libg1m handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @return the error code (0 if ok).
*/
int g1m_parse_fkey_cg_content(g1m_t *handle, FILE *stream,
int g1m_decode_fkey_cg_content(g1m_t *handle, g1m_buffer_t *buffer,
uint_fast32_t zonesize, uint32_t *pchecksum)
{
handle->type = 0x00;
//handle->type = g1m_type_fkey;
(void)stream;
(void)buffer;
(void)zonesize;
(void)pchecksum;
return (g1m_error_magic);

View File

@ -1,10 +1,10 @@
/* ************************************************************************** */
/* _____ _ */
/* parse/lang.c |_ _|__ _ _| |__ ___ _ _ */
/* decode/lang.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/12/01 13:33:45 |___/ */
/* Last updated: 2017/02/19 23:01:18 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
@ -13,15 +13,15 @@
/* fx language files parsing */
/* ************************************************************************** */
/**
* g1m_parse_lang:
* Parse fx language files.
* g1m_decode_lang:
* Decode fx language files.
*
* @arg handle the libg1m handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @return the error code (0 if ok).
*/
int g1m_parse_lang(g1m_t *handle, FILE *stream,
int g1m_decode_lang(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
(void)std;
@ -92,17 +92,17 @@ fail:
/* cg language files parsing */
/* ************************************************************************** */
/**
* g1m_parse_lang_cg_content:
* Parse the content of the message zone size for a G3L language file.
* g1m_decode_lang_cg_content:
* Decode the content of the message zone size for a G3L language file.
*
* @arg handle the libg1m handle.
* @arg stream the stream to read from.
* @arg buffer the buffer to read from.
* @arg zonesize the message zone size.
* @arg pchecksum pointer to the checksum to contribute to.
* @return the error code (0 if ok).
*/
static int g1m_parse_lang_cg_content(g1m_t *handle, FILE *stream,
static int g1m_decode_lang_cg_content(g1m_t *handle, g1m_buffer_t *buffer,
uint_fast32_t zonesize, uint32_t *pchecksum)
{
int err; uint32_t checksum = *pchecksum;
@ -183,16 +183,16 @@ fail:
}
/**
* g1m_parse_lang_cg:
* Parse fx-CG language files.
* g1m_decode_lang_cg:
* Decode fx-CG language files.
*
* @arg handle the libg1m handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg std the standard header.
* @return the error code (0 if ok).
*/
int g1m_parse_lang_cg(g1m_t *handle, FILE *stream,
int g1m_decode_lang_cg(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
/* set handle type */
@ -224,7 +224,7 @@ int g1m_parse_lang_cg(g1m_t *handle, FILE *stream,
size_t zonesize = hd.filesize - sizeof(struct standard_header)
- sizeof(struct g3l_subheader) - sizeof(struct g3l_footer);
if (hd.magic[0] == 0x04)
err = g1m_parse_lang_cg_content(handle, stream, zonesize, &checksum);
err = g1m_decode_lang_cg_content(handle, buffer, zonesize, &checksum);
else return (g1m_error_magic);
if (err) return (g1m_error_magic);

View File

@ -1,10 +1,10 @@
/* ************************************************************************** */
/* _____ _ */
/* parse/main.c |_ _|__ _ _| |__ ___ _ _ */
/* decode/main.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/12/01 13:33:45 |___/ */
/* Last updated: 2017/02/19 23:01:18 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
@ -18,66 +18,65 @@ struct corresp {
unsigned int type;
/* result */
int (*read)(g1m_t*, FILE*, struct standard_header*);
g1m_decode_function *decode;
};
/* The correspondances */
static struct corresp parsing_functions[] = {
/* add-ins */
{g1m_platform_fx, g1m_type_addin,
g1m_parse_addin},
g1m_decode_addin},
{g1m_platform_cg, g1m_type_addin,
g1m_parse_addin_cg},
g1m_decode_addin_cg},
/* mcs */
{g1m_platform_fx, g1m_type_mcs,
g1m_parse_mcs},
g1m_decode_mcs},
{g1m_platform_cg, g1m_type_mcs,
g1m_parse_mcs},
g1m_decode_mcs},
/* language files */
{g1m_platform_fx, g1m_type_lang,
g1m_parse_lang},
g1m_decode_lang},
{g1m_platform_cg, g1m_type_lang,
g1m_parse_lang_cg},
g1m_decode_lang_cg},
/* function keys file */
{g1m_platform_fx, g1m_type_fkey,
g1m_parse_fkey},
g1m_decode_fkey},
{g1m_platform_cg, g1m_type_fkey,
g1m_parse_lang_cg},
g1m_decode_lang_cg},
/* e-activities */
{g1m_platform_fx, g1m_type_eact,
g1m_parse_eact},
g1m_decode_eact},
/* pictures */
{g1m_platform_cg, g1m_type_pict,
g1m_parse_g3p},
g1m_decode_g3p},
{g1m_platform_cp, g1m_type_pict,
g1m_parse_c2p},
g1m_decode_c2p},
/* storage */
{g1m_platform_none, g1m_type_storage,
g1m_parse_storage},
/*{g1m_platform_none, g1m_type_storage,
g1m_decode_storage},*/
{0, 0, NULL}
};
/**
* find_parse_function:
* find_decode_function:
* Find the parsing function.
*
* @arg handle the handle.
* @arg path the file path.
* @arg std pointer to the standard header.
* @arg rd pointer to the read function.
* @arg rd pointer to the decode function.
* @return the error code (0 if ok).
*/
static int find_parse_function(g1m_t *handle, const char *path,
struct standard_header *std,
int (**rd)(g1m_t*, FILE*, struct standard_header*))
static int find_decode_function(g1m_t *handle, const char *path,
struct standard_header *std, g1m_decode_function **rd)
{
/* get the type */
unsigned int platform, type;
@ -99,7 +98,7 @@ static int find_parse_function(g1m_t *handle, const char *path,
/* look for corresponding parsing function */
struct corresp *c = parsing_functions - 1;
while ((++c)->read) {
while ((++c)->decode) {
if (c->type != type)
continue;
if (c->platform != platform)
@ -107,7 +106,7 @@ static int find_parse_function(g1m_t *handle, const char *path,
break;
}
if (!c->read) {
if (!c->decode) {
log_fatal("No parsing function was found for this type.");
return (g1m_error_magic);
}
@ -115,7 +114,7 @@ static int find_parse_function(g1m_t *handle, const char *path,
/* set the vars */
handle->type = type;
handle->platform = platform;
*rd = c->read;
*rd = c->decode;
return (0);
}
@ -123,20 +122,20 @@ static int find_parse_function(g1m_t *handle, const char *path,
/* Main parsing function */
/* ************************************************************************** */
/**
* g1m_parse:
* Parse a G1M file.
* g1m_decode:
* Decode a G1M file.
*
* Read the standard header, correct endianness, check magic numbers,
* then read subparts according to the G1M type.
*
* @arg handle the handle.
* @arg path the file path.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg expected_type the expected type.
* @return the error code (0 if ok).
*/
int g1m_parse(g1m_t *handle, const char *path, FILE *stream,
int g1m_decode(g1m_t *handle, const char *path, g1m_buffer_t *buffer,
g1m_type_t expected_type)
{
/* initialize the handle */
@ -158,8 +157,8 @@ int g1m_parse(g1m_t *handle, const char *path, FILE *stream,
hd.number = be16toh(hd.number);
/* get type */
int (*read_func)(g1m_t*, FILE*, struct standard_header*); int err;
if ((err = find_parse_function(handle, path, &hd, &read_func)))
g1m_decode_function *read_func; int err;
if ((err = find_decode_function(handle, path, &hd, &read_func)))
return (err);
/* check if the type is alright */
@ -170,6 +169,6 @@ int g1m_parse(g1m_t *handle, const char *path, FILE *stream,
log_info("Standard Header filesize is %" PRIu32 "o.", hd.filesize);
log_info("Standard Header num is %" PRIu16 ".", hd.number);
/* subparse. */
return ((*read_func)(handle, stream, &hd));
/* subdecode. */
return ((*read_func)(handle, buffer, &hd));
}

View File

@ -1,10 +1,10 @@
/* ************************************************************************** */
/* _____ _ */
/* parse/mcs.c |_ _|__ _ _| |__ ___ _ _ */
/* decode/mcs.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/12/01 13:33:45 |___/ */
/* Last updated: 2017/02/19 23:01:18 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
@ -17,13 +17,13 @@
* get_image:
* Allocate space, and convert monochromic image to 0x0RGB.
*
* @arg stream the stream from which to read.
* @arg buffer the buffer to read from.
* @arg img the image to make.
* @arg width the image width.
* @arg height the image height.
*/
static int get_image(FILE *stream, uint32_t ***img,
static int get_image(g1m_buffer_t *buffer, uint32_t ***img,
unsigned int width, unsigned int height)
{
/* get raw pixels */
@ -67,16 +67,16 @@ static int get_image(FILE *stream, uint32_t ***img,
/* MCS file parsing */
/* ************************************************************************** */
/**
* mcs_parse_program:
* Parse a program.
* mcs_decode_program:
* Decode a program.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_parse_program(g1m_mcsfile_t *handle, FILE *stream,
static int mcs_decode_program(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read header */
@ -103,16 +103,16 @@ static int mcs_parse_program(g1m_mcsfile_t *handle, FILE *stream,
}
/**
* mcs_parse_spreadsheet:
* Parse a spreadsheet.
* mcs_decode_spreadsheet:
* Decode a spreadsheet.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_parse_spreadsheet(g1m_mcsfile_t *handle, FILE *stream,
static int mcs_decode_spreadsheet(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read header */
@ -138,7 +138,7 @@ static int mcs_parse_spreadsheet(g1m_mcsfile_t *handle, FILE *stream,
uint_fast32_t cols = 0;
/* log some info */
log_info("%" PRIuFAST32 " columns to parse!", colcount);
log_info("%" PRIuFAST32 " columns to read!", colcount);
if (colcount) {
/* get the column directory */
@ -228,16 +228,16 @@ static int mcs_parse_spreadsheet(g1m_mcsfile_t *handle, FILE *stream,
}
/**
* mcs_parse_list:
* Parse an List.
* mcs_decode_list:
* Decode an List.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg size the length.
* @return the error code (0 if ok).
*/
static int mcs_parse_list(g1m_mcsfile_t *handle, FILE *stream,
static int mcs_decode_list(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t size)
{
/* read header */
@ -323,16 +323,16 @@ static int mcs_parse_list(g1m_mcsfile_t *handle, FILE *stream,
}
/**
* mcs_parse_matrix:
* Parse a matrix.
* mcs_decode_matrix:
* Decode a matrix.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_parse_matrix(g1m_mcsfile_t *handle, FILE *stream,
static int mcs_decode_matrix(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
g1m_mcs_cell_t **tab, *rws;
@ -427,16 +427,16 @@ fail:
}
/**
* mcs_parse_capture:
* Parse a capture.
* mcs_decode_capture:
* Decode a capture.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_parse_capture(g1m_mcsfile_t *handle, FILE *stream,
static int mcs_decode_capture(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read header */
@ -454,20 +454,20 @@ static int mcs_parse_capture(g1m_mcsfile_t *handle, FILE *stream,
log_info("capture is %dx%d sized", handle->width, handle->height);
/* get the image and return */
return (get_image(stream, &handle->image, handle->width, handle->height));
return (get_image(buffer, &handle->image, handle->width, handle->height));
}
/**
* mcs_parse_picture:
* Parse a picture.
* mcs_decode_picture:
* Decode a picture.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_parse_picture(g1m_mcsfile_t *handle, FILE *stream,
static int mcs_decode_picture(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
int err;
@ -477,13 +477,13 @@ static int mcs_parse_picture(g1m_mcsfile_t *handle, FILE *stream,
handle->height = 64;
/* get the first image */
if ((err = get_image(stream, &handle->image, 128, 64))) {
if ((err = get_image(buffer, &handle->image, 128, 64))) {
log_fatal("Failed to get the first image.");
return (err);
}
/* and the second */
if ((err = get_image(stream, &handle->second_image, 128, 64))) {
if ((err = get_image(buffer, &handle->second_image, 128, 64))) {
log_fatal("Failed to get the second image.");
return (err);
}
@ -493,16 +493,16 @@ static int mcs_parse_picture(g1m_mcsfile_t *handle, FILE *stream,
}
/**
* mcs_parse_string:
* Parse string.
* mcs_decode_string:
* Decode an MCS string.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_parse_string(g1m_mcsfile_t *handle, FILE *stream,
static int mcs_decode_string(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
(void)handle;
@ -515,16 +515,16 @@ static int mcs_parse_string(g1m_mcsfile_t *handle, FILE *stream,
}
/**
* mcs_parse_setup:
* Parse settings.
* mcs_decode_setup:
* Decode settings.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_parse_setup(g1m_mcsfile_t *handle, FILE *stream,
static int mcs_decode_setup(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
(void)handle;
@ -535,16 +535,16 @@ static int mcs_parse_setup(g1m_mcsfile_t *handle, FILE *stream,
}
/**
* mcs_parse_alphamem:
* Parse alphamem.
* mcs_decode_alphamem:
* Decode alpha memory (variables).
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_parse_alphamem(g1m_mcsfile_t *handle, FILE *stream,
static int mcs_decode_alphamem(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read the data */
@ -589,63 +589,63 @@ static int mcs_parse_alphamem(g1m_mcsfile_t *handle, FILE *stream,
/* Type correspondance list */
/* ************************************************************************** */
/* MCS file parsing function type */
typedef int (*mcs_parse_func_t)(g1m_mcsfile_t*, FILE*, uint_fast32_t);
typedef int (*mcs_decode_func_t)(g1m_mcsfile_t*, g1m_buffer_t*, uint_fast32_t);
/* Correspondance type */
struct mcs_corresp {
unsigned int type;
mcs_parse_func_t parse;
mcs_decode_func_t decode;
};
/* All correspondances */
static struct mcs_corresp mcs_types[] = {
{g1m_mcstype_program, mcs_parse_program,},
{g1m_mcstype_list, mcs_parse_list},
{g1m_mcstype_mat, mcs_parse_matrix},
{g1m_mcstype_vct, mcs_parse_matrix},
{g1m_mcstype_spreadsheet, mcs_parse_spreadsheet},
{g1m_mcstype_pict, mcs_parse_picture},
{g1m_mcstype_capt, mcs_parse_capture},
{g1m_mcstype_string, mcs_parse_string},
{g1m_mcstype_setup, mcs_parse_setup},
{g1m_mcstype_alphamem, mcs_parse_alphamem},
{g1m_mcstype_program, mcs_decode_program,},
{g1m_mcstype_list, mcs_decode_list},
{g1m_mcstype_mat, mcs_decode_matrix},
{g1m_mcstype_vct, mcs_decode_matrix},
{g1m_mcstype_spreadsheet, mcs_decode_spreadsheet},
{g1m_mcstype_pict, mcs_decode_picture},
{g1m_mcstype_capt, mcs_decode_capture},
{g1m_mcstype_string, mcs_decode_string},
{g1m_mcstype_setup, mcs_decode_setup},
{g1m_mcstype_alphamem, mcs_decode_alphamem},
{}
};
/**
* lookup_mcsfile_parse:
* 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_parse_func_t lookup_mcsfile_parse(unsigned int type)
static mcs_decode_func_t lookup_mcsfile_decode(unsigned int type)
{
/* lookup for the type */
struct mcs_corresp *c = mcs_types;
while (c->parse) {
while (c->decode) {
if (type == c->type)
break;
c++;
}
/* return the function */
return (c->parse);
return (c->decode);
}
/* ************************************************************************** */
/* Public API functions */
/* ************************************************************************** */
/**
* g1m_parse_mcsfile_content:
* Parse MCS file content.
* g1m_decode_mcsfile_content:
* 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.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg raw_type the raw file type.
* @arg groupname the groupname (up to 16 bytes to read).
* @arg dirname the directory name (up to 8 bytes are read).
@ -654,7 +654,7 @@ static mcs_parse_func_t lookup_mcsfile_parse(unsigned int type)
* @return the error code (0 if ok).
*/
int g1m_parse_mcsfile_content(g1m_mcsfile_t **handle, FILE *stream,
int g1m_decode_mcsfile_content(g1m_mcsfile_t **handle, g1m_buffer_t *buffer,
int raw_type, const unsigned char *groupname,
const unsigned char *dirname, const unsigned char *filename,
uint_fast32_t filesize)
@ -684,8 +684,8 @@ int g1m_parse_mcsfile_content(g1m_mcsfile_t **handle, FILE *stream,
}
/* look for the parsing function */
mcs_parse_func_t parse = lookup_mcsfile_parse(type);
if (!parse) {
mcs_decode_func_t decode = lookup_mcsfile_decode(type);
if (!decode) {
log_error("No dedicated parsing function for this type was found!");
goto notparsing;
}
@ -693,7 +693,7 @@ int g1m_parse_mcsfile_content(g1m_mcsfile_t **handle, FILE *stream,
/* read it */
h->type = type;
strncpy(h->name, (char*)filename, 8);
int err = (*parse)(h, stream, filesize);
int err = (*decode)(h, buffer, filesize);
/* free if error, and return */
if (err) {
@ -722,16 +722,16 @@ notparsing:;
}
/**
* g1m_parse_mcs:
* Parse an MCS file, after the Standard Header.
* g1m_decode_mcs:
* Decode an MCS file, after the Standard Header.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg num number of sizes.
* @return the error code (0 if ok).
*/
int g1m_parse_mcs(g1m_t *handle, FILE *stream,
int g1m_decode_mcs(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
int err = g1m_error_alloc;
@ -776,8 +776,8 @@ int g1m_parse_mcs(g1m_t *handle, FILE *stream,
/* decode */
handle->files[handle->count] = NULL;
err = g1m_parse_mcsfile_content(&handle->files[handle->count],
stream, fhd.filetype, hd.intname, fhd.dirname,
err = g1m_decode_mcsfile_content(&handle->files[handle->count],
buffer, fhd.filetype, hd.intname, fhd.dirname,
fhd.filename, fhd.datalength);
if (err) return (err);
handle->count++;

View File

@ -1,10 +1,10 @@
/* ************************************************************************** */
/* _____ _ */
/* parse/picture.c |_ _|__ _ _| |__ ___ _ _ */
/* decode/picture.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/12/01 13:33:45 |___/ */
/* Last updated: 2017/02/19 23:01:18 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
@ -27,16 +27,16 @@ static void g3p_deobfuscate(uint8_t *buf, size_t n)
}
/**
* g1m_parse_g3p:
* Parse a G3P file.
* g1m_decode_g3p:
* Decode a G3P file.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @arg std the standard header.
* @return the error code (0 if ok).
*/
int g1m_parse_g3p(g1m_t *handle, FILE *stream,
int g1m_decode_g3p(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
/* get the G3P global header */
@ -133,20 +133,20 @@ int g1m_parse_g3p(g1m_t *handle, FILE *stream,
}
/**
* g1m_parse_c2p:
* Parse Classpad images.
* g1m_decode_c2p:
* Decode Classpad images.
*
* @arg handle the handle.
* @arg stream the stream to parse from.
* @arg buffer the buffer to read from.
* @return the error code (0 if ok).
*/
int g1m_parse_c2p(g1m_t *handle, FILE *stream,
int g1m_decode_c2p(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
(void)std;
(void)handle;
(void)stream;
(void)buffer;
/* TODO */
log_info("C2P files are not managed yet.");
log_info("Size is %" PRIuSIZE " o", sizeof(struct c2p_subheader));

113
src/decode/storage.c.draft Normal file
View File

@ -0,0 +1,113 @@
/* ************************************************************************** */
/* _____ _ */
/* decode/storage.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2017/02/19 23:01:18 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
#define MAX_SECTORS 27
#define SUB(V, TYPE) \
case storage_entrytype_##TYPE:; struct storage_##TYPE *V = \
(struct storage_##TYPE*)&entry->raw_subheader;
/* ************************************************************************** */
/* Main functions */
/* ************************************************************************** */
/**
* g1m_decode_storage:
* Decode storage files.
*
* @arg handle the libg1m handle.
* @arg buffer the buffer to read from.
* @arg std the standard header.
* @return the error code (0 if ok).
*/
int g1m_decode_storage(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
(void)std; int err, ret = 0;
handle->type = 0x00;
log_info("Storage memory!");
/* skip the first 0x270000 - 0x20 bytes */
SKIP(0x270000 - sizeof(struct standard_header))
/* get the entries */
struct storage_entry storage_entries[0x800];
READ(storage_entries, 0x800 * sizeof(struct storage_entry))
/* read the sectors and directories */
uint32_t sectors[MAX_SECTORS] = {0}; /* sectors offsets */
uint32_t max_sector_end = 0;
for (int id = 0; id < 0x800; id++) {
struct storage_entry *entry = storage_entries[id];
entry->type = be16toh(entry.type);
entry->uuid = be16toh(entry.uuid);
int special = (entry.type & 0xF000) >> 12;
switch (entry.type & 0xFFF) {
SUB(sh, sector)
uint32_t addr = be32toh(sh->startaddr);
uint32_t logical = be32toh(sh->logical_sector_number);
if (addr > max_sector_end)
max_sector_end = addr;
if (logical != 0xFFFFFFFF)
sectors[logical] - 0x290000;
break;
SUB(dh, directory)
int active = (special == 0x05);
dh->name;
break;
}
}
/* correct sector end, and calculate how much data we need to gather */
max_sector_end = max_sector_end + 0x10000;
uint8_t *buf = malloc(max_sector_end - 0x290000);
if (!buf) return (g1m_error_alloc);
GREAD(buf, max_sector_end - 0x290000);
/* look for files and fragments */
for (int id = 0; id < 0x800; id++) {
struct storage_entry *entry = storage_entries[id];
/* check that entry is a directory */
if ((entry->type & 0xFFF) != storage_entrytype_file
|| !entry->uuid) continue;
int special = (entry.type & 0xF000) >> 12;
/* get subheader */
struct storage_file *fh =
(struct storage_file*)entry->raw_subheader;
fh->directory_reference = be16toh(fh->directory_number);
fh->directory_number = be16toh(fh->directory_number);
/* check if is in a directory */
unsigned int indir = 0;
//if (fh->directory_reference != 0xFFFF &&
if (fh->directory_reference == storage_entrytype_directory)
indir = fh->directory_number;
/* work out */
uint_fast32_t size = 0;
int id_f = id;
for (; id_f < 0x800; id_f++) {
/* check that entry is fragment */
struct storage_entry *entry = storage_entries[id_f];
if ((entry.type & 0xFFF) != storage_entrytype_fragment) break;
/* add size */
size += used_bytes;
}
}
/* no error */
ret = 0;
fail:
free(buf);
return (ret);
}

View File

@ -1,84 +0,0 @@
/* ************************************************************************** */
/* _____ _ */
/* fontcharacter/character.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/11/21 13:29:30 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
#include <string.h>
/**
* g1m_mbtofc:
* Multi-byte to FONTCHARACTER.
*
* Based on what is said in the fx-9860G SDK.
* Let's hope it stays true.
*
* Based on how `mbtowc` works.
*
* @arg pfc pointer to the FONTCHARACTER character.
* @arg s the multi-byte source string.
* @arg n the size of the destination buffer.
* @return the number of bytes used (-1 if error).
*/
int g1m_mbtofc(FONTCHARACTER *pfc, const char *s, size_t n)
{
/* null string? */
if (!s) return (-1);
/* so that the 'no size = unlimited' (n == 0) case is easy to manage */
n--;
/* nul character? */
if (!*s)
return (0);
/* extended char? */
const unsigned char *us = (const unsigned char*)s;
if (*us && strchr("\x7F\xF7\xF9\xE5\xE6\xE7", *us)) {
if (!n) return (-1);
*pfc = *us;
*pfc <<= 8;
*pfc |= *(us + 1);
return (2);
}
/* single-byte character! */
*pfc = *us;
return (1);
}
/**
* g1m_fctomb:
* FONTCHARACTER to multi-byte.
*
* Based on the same document, and on how `wctomb` works.
*
* Do you think a battery has self-consciousness?
*
* @arg s pointer to the multi-byte string.
* @arg fc the FONTCHARACTER character.
* @return the
*/
int g1m_fctomb(char *s, FONTCHARACTER fc)
{
/* no string? */
if (!s)
return (-1);
/* extended? */
if (fc > 0xff) {
*s++ = (fc >> 8) & 0xff;
*s = fc & 0xff;
return (2);
}
/* normal char. */
*s = fc;
return (fc != 0);
}

View File

@ -1,84 +0,0 @@
/* ************************************************************************** */
/* _____ _ */
/* fontcharacter/string.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/11/21 13:29:30 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
#include <string.h>
/**
* g1m_mbstofcs:
* Multi-byte string to FONTCHARACTER string.
*
* This function imitates `mbstowcs` (unicode), but for CASIO's encoding.
* You should be able to use it the same way.
*
* @arg dest the destination.
* @arg src the source.
* @arg n the size of the source.
* @return the size of the destination.
*/
size_t g1m_mbstofcs(FONTCHARACTER *dest, const char *src, size_t n)
{
size_t len = 0;
n--; /* terminating character */
while (n--) {
/* read the FONTCHARACTER char */
FONTCHARACTER fc;
int count = g1m_mbtofc(&fc, src, 0);
if (count <= 0)
break;
/* write the entry and iterate */
if (dest) *dest++ = fc;
src += count;
len++;
}
/* write the terminating entry and return length */
if (dest) *dest = 0;
return (len);
}
/**
* g1m_fcstombs:
* FONTCHARACTER string to multi-byte string conversion.
*
* This function imitates `wcstombs` (unicode), but for CASIO's encoding.
* You should be able to use it the same way.
*
* @arg dst the destination.
* @arg src the source.
* @arg n the size of the source.
* @return the size of the destination.
*/
size_t g1m_fcstombs(char *dst, const FONTCHARACTER *src, size_t n)
{
char buf[2];
size_t len = 0;
n--; /* terminating character */
/* main loop */
while (n--) {
/* to multi-byte */
int count = g1m_fctomb(buf, *src++);
if (count <= 0) break;
/* copy */
if (dst) {
memcpy(dst, buf, count);
dst += count;
}
len += count;
n -= count;
}
if (dst) *dst = 0;
return (len);
}

View File

@ -1,125 +0,0 @@
/* ************************************************************************** */
/* _____ _ */
/* parse/storage.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/12/25 13:38:52 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
#define SUB(V, TYPE) \
case storage_entrytype_##TYPE:; \
struct storage_##TYPE *V = (struct storage_##TYPE*)&entry.raw_subheader;
/**
* rawfctombs:
* Temporary function, from raw FONTCHARACTER to multi-byte using buffers.
*
* @arg raw the raw buffer
* @arg count the number of fontcharacters in the count
* @arg final the final multi-byte buffer
*/
static void rawfctombs(FONTCHARACTER *raw, int count, char *final)
{
/* copy the raw data into a null-terminated buffer */
FONTCHARACTER traw[count + 1]; traw[count] = 0;
memcpy(traw, raw, count * sizeof(FONTCHARACTER));
/* big endian to host the raw buffer, and null terminate it */
int i;
for (i = 0; traw[i] != 0xffff && i < count; i++)
traw[i] = be16toh(traw[i]);
traw[i] = 0;
g1m_fcstombs(final, traw, 0);
}
/**
* g1m_parse_storage:
* Parse storage files.
*
* @arg handle the libg1m handle.
* @arg stream the stream to read from.
* @arg std the standard header.
* @return the error code (0 if ok).
*/
int g1m_parse_storage(g1m_t *handle, FILE *stream,
struct standard_header *std)
{
(void)std;
handle->type = 0x00;
/* skip the first 0x270000 - 0x20 bytes */
SKIP(0x270000 - sizeof(struct standard_header))
/* read */
log_info("Storage memory!");
/* read the entries */
for (int id = 1; id < 0x800; id++) {
/* read the entry */
DREAD(entry, storage_entry)
if (entry.type == 0xFFFF)
continue;
entry.type = be16toh(entry.type);
entry.uuid = be16toh(entry.uuid);
/* read it */
int special = (entry.type & 0xF000) >> 12;
switch (entry.type & 0xFFF) {
SUB(sh, sector)
int unused = (sh->logical_sector_number == 0xFFFFFFFF);
log_info("[%02d,%02" PRIu16 "] Is a%ssector.", id, entry.uuid,
(unused) ? "n unused " : " ");
sh->startaddr = be32toh(sh->startaddr);
log_info("- Starts at address 0x%08" PRIx32, sh->startaddr);
#if LOGLEVEL <= ll_info
sh->logical_sector_number = be32toh(sh->logical_sector_number);
if (!unused) log_info("- Logical number: 0x%08" PRIu32,
sh->logical_sector_number);
#endif
break;
SUB(dh, directory)
log_info("[%02d,%02" PRIu16 "] Is a%s directory.", id, entry.uuid,
(special == 0x05) ? "n active" : " deleted");
#if LOGLEVEL <= ll_info
char dirname[25]; rawfctombs(dh->name, 12, dirname);
log_info("- Directory name: %s", dirname);
#endif
break;
SUB(fh, file)
log_info("[%02d,%02" PRIu16 "] Is a%s file.", id, entry.uuid,
(special == 0x05) ? "n active" : " deleted");
#if LOGLEVEL <= ll_info
char filename[25]; rawfctombs(fh->name, 12, filename);
log_info("- File name: %s", filename);
if (be16toh(fh->directory_reference) == storage_entrytype_directory)
log_info("- Is in directory #%" PRIu16,
be16toh(fh->directory_number));
else log_info("- Is in root.");
#endif
break;
SUB(fgh, fragment)
log_info("[%02d,%02" PRIu16 "] Is a fragment.", id, entry.uuid);
log_info("- Points at sector #%" PRIu16,
be16toh(fgh->fragment_sector_id));
log_info("- Is %" PRIu16 "/%" PRIu16
" (%" PRIu16 "o at offset 0x%04" PRIx16 ")",
be16toh(fgh->fragment_id), be16toh(fgh->fragment_count),
be16toh(fgh->used_bytes), be16toh(fgh->used_bytes_offset));
break;
default: /* we should know all of the types, but we never know */
log_info("[%02d,%02" PRIu16 "] Is unknown.", id, entry.uuid);
}
}
/* no error */
return (0);
}

View File

@ -62,8 +62,14 @@ int g1m_fopen(g1m_t **handle, const char *path, FILE *stream,
*handle = malloc(sizeof(g1m_t));
if (!*handle) return (g1m_error_alloc);
/* make the buffer */
g1m_buffer_t buffer = {
.cookie = stream,
.read = g1m_filebuffer_read
};
/* fill it by parsing opened file */
if ((err = g1m_parse(*handle, path, stream, expected))) {
if ((err = g1m_decode(*handle, path, &buffer, expected))) {
free(*handle);
*handle = NULL;
return (err);

37
src/utils/filebuffer.c Normal file
View File

@ -0,0 +1,37 @@
/* ************************************************************************** */
/* _____ _ */
/* utils/filebuffer.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2017/02/19 22:35:20 |___/ */
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
#ifndef G1M_DISABLED_FILE
/**
* g1m_filebuffer_read:
* Read from a filebuffer.
*
* @arg vcookie the FILE* (uncasted)
* @arg buf the buffer to fill.
* @arg size the size to read.
* @return the error (if any).
*/
int g1m_filebuffer_read(void *vcookie, unsigned char *buf, size_t size)
{
FILE *file = (void*)vcookie;
size_t read = fread(buf, 1, size, file);
if (!read) {
log_error("READING failed: read %" PRIuSIZE "/%" PRIuSIZE
" bytes, %" PRIuSIZE " missing.", read, size, size - read);
return (g1m_error_eof);
}
/* no error */
return (0);
}
#endif

View File

@ -10,69 +10,43 @@
#include <libg1m/internals.h>
/**
* g1m_parse_skip:
* g1m_skip:
* Skip some bytes.
*
* I've made two loops to avoid conditions in each loop iteration
* when checksum is not calculated.
* when checksum is not calculated. Yeah, I know. #YOLO.
*
* @arg stream the stream where to skip bytes.
* @arg buffer the buffer from which to read.
* @arg size the size to skip.
* @arg checksum pointer to the checksum variable if there is one.
*/
int g1m_parse_skip(FILE *stream, size_t size, uint_fast32_t *checksum)
int g1m_skip(g1m_buffer_t *buffer, size_t size, uint_fast32_t *checksum)
{
uint8_t buf[1024];
#if LOGLEVEL <= ll_error
size_t size_ini = size;
#endif
uint8_t buf[1024]; int err;
size_t rd = 0; uint_fast32_t add = 0;
if (checksum) {
uint_fast32_t add = 0;
while (1) {
/* if no size left, exit */
if (!size) break;
while (1) {
/* if no size left, exit */
if (!size) break;
/* read that much */
{
size_t curlen = min(size, 1024);
size_t read_len = fread(buf, 1, curlen, stream);
size -= read_len;
if (read_len < curlen) {
log_error("SKIPPING failed, skipped "
"%" PRIuSIZE "/%" PRIuSIZE " bytes, "
"%" PRIuSIZE " missing",
size_ini - size, size_ini, size);
return (g1m_error_eof);
}
/* feed the checksum */
add = g1m_checksum32(buf, curlen, add);
/* read that much */
{
size_t curlen = min(size, 1024);
if ((err = (*buffer->read)(buffer->cookie, buf, curlen))) {
log_error("Skipping has failed after %zu bytes", size);
return (err);
}
}
*checksum += add;
} else {
while (1) {
/* if no size left, exit */
if (!size) break;
rd += curlen;
/* read that much */
{
size_t curlen = min(size, 1024);
size_t read_len = fread(buf, 1, curlen, stream);
size -= read_len;
if (read_len < curlen) {
log_error("SKIPPING failed, skipped "
"%" PRIuSIZE "/%" PRIuSIZE " bytes, "
"%" PRIuSIZE " missing",
size_ini - size, size_ini, size);
return (g1m_error_eof);
}
}
/* feed the checksum */
add = g1m_checksum32(buf, curlen, add);
}
}
/* add to checksum */
if (checksum) *checksum += add;
/* no error */
return (0);
}

@ -1 +0,0 @@
Subproject commit 2f4680d042f84787bf39fb93e4448599b5e2baa3

View File

@ -1 +0,0 @@
.fontcharacter-root/fontcharacter

@ -1 +0,0 @@
Subproject commit 1f382d0797f7534df408e858a9182bd11c9dddea

View File

@ -3,24 +3,53 @@
# Arguments #
#******************************************************************************#
# Initialize the variables
gint=
no_file=
version=
# Read the arguments
for arg ; do case "$arg" in
--gint) gint=y ;;
--no-file) no_file=y ;;
--version=*) version="${arg#*=}" ;;
*) echo "'${arg}': Did not read." ;;
esac; done
# Make version as numbers
vnum=$(echo ${version} | cut -d- -f1)
version_major=$(( $(echo ${vnum} | cut -d. -f1) ))
version_minor=$(( $(echo ${vnum} | cut -s -d. -f2) ))
version_rev=$(( $(echo ${vnum} | cut -s -d. -f3) ))
version_indev=$(echo ${version} | cut -s -d- -f2)
version_indev=$([ ${version_indev} ] && echo 1 || echo 0)
# Constitute version thingies
version_num=$(printf "0x%02X%02X%04X" \
${version_major} ${version_minor} ${version_rev})
#******************************************************************************#
# Write the file #
#******************************************************************************#
# Beginning
cat <<_EOF
#ifndef LIBG1M_CONFIG_H
# define LIBG1M_CONFIG_H
# define LIBG1M_VERSION "${version}"
# define LIBG1M_VERNUM ${version_num}
# define LIBG1M_MAJOR ${version_major}
# define LIBG1M_MINOR ${version_minor}
# define LIBG1M_REV ${version_rev}
# define LIBG1M_INDEV ${version_indev}
# --- no option yet! ---
_EOF
# File part
if [ "$no_file" ]; then cat <<_EOF
/* FILE interface is disabled */
# define G1M_DISABLED_FILE 1
_EOF
fi
# End of the file
cat <<_EOF
#endif /* LIBG1M_CONFIG_H */
_EOF