cake
/
libg1m
Archived
1
0
Fork 0

Reorganized lib sources.

This commit is contained in:
Thomas Touhey 2017-02-28 15:01:21 +01:00
parent d436ce2791
commit aba8d1db06
38 changed files with 1346 additions and 982 deletions

View File

@ -94,23 +94,23 @@ dist: mrproper
all-lib: $(CHECKCFG) $(if $(STATIC),$(ANAME),$(SONAME))
# Make a module object directory.
$(MODULES:%=$(OBJDIR)/%):
$(OBJDIR)/ $(DIRS:%=$(OBJDIR)/%):
$(call bcmd,mkdir,$@,$(MD) $@)
# Make a module object out of a module source file.
define make-moduleobj-rule
$(OBJDIR)/$1/%.o: $(SRCDIR)/$1/%.c $(INC) | $(OBJDIR)/$1
# Make an object out of a source file.
define make-obj-rule
$(OBJDIR)/$1.o: $(SRCDIR)/$1.c $(INC) | $(dir $(OBJDIR)/$1)
$(call bcmd,cc,$$@,$(CC) -c -o $$@ $$< $(CFLAGS))
endef
$(foreach mod,$(MODULES), \
$(eval $(call make-moduleobj-rule,$(mod))))
$(foreach src,$(SRC),\
$(eval $(call make-obj-rule,$(src))))
# Make the shared library.
$(SONAME): $(foreach m,$(MODULES),$(SRC_$(m):%=$(OBJDIR)/$(m)/%.o))
$(SONAME): $(SRC:%=$(OBJDIR)/%.o)
$(call bcmd,ld,$@,$(LD) -o $@ $^ $(LDFLAGS))
# Make the static library.
lib$(NAME).a: $(foreach m,$(MODULES),$(SRC_$(m):%=$(OBJDIR)/$(m)/%.o))
lib$(NAME).a: $(SRC:%=$(OBJDIR)/%.o)
$(call bcmd,ar rc,$@,$(AR) rcs $@ $^)
# Remove the objects directory.
@ -138,7 +138,7 @@ $(eval $(call make-moduleobj-rule,$(mod))))
$(if $(FOR_WINDOWS),lib$(NAME).dll.a,$(SONAME))))
$(if $(IWINDLL),$(call qcmd,$(INST) -m 755 -d "$(IBINDIR)"))
$(if $(IWINDLL),$(call qcmd,$(INST) -m 644 -t "$(IBINDIR)" \
$(if $(IWINDLL),$(call qcmd,$(INST) -m 755 -t "$(IBINDIR)" \
lib$(NAME).dll))
$(if $(LINK_TO_MAJOR),\
@ -166,8 +166,11 @@ $(eval $(call make-moduleobj-rule,$(mod))))
$(call qcmd,$(RM) "$(IINCDIR)/lib$(NAME).h")
$(call qcmd,$(RM) -r "$(IINCDIR)/lib$(NAME)")
# Reinstall the library and development files.
reinstall-lib: uninstall-lib install-lib
.PHONY: all-lib mostlyclean-lib mclean-lib clean-lib re-lib
.PHONY: install-lib uninstall-lib
.PHONY: install-lib uninstall-lib reinstall-lib
#******************************************************************************#
# Configuration tools-related #
#******************************************************************************#

View File

@ -122,28 +122,18 @@ endif
GZIP := gzip -f
#******************************************************************************#
# Look for modules and modules sources #
# Look up the sources and includes #
#******************************************************************************#
# Look for modules first
MODULES := $(notdir $(shell find $(SRCDIR) -mindepth 1 -maxdepth 1 \
-type d | sort))
# Look up the sources
SRC := $(basename $(shell find $(SRCDIR) -mindepth 1 -type f \
-name "*.c" -printf "%P\n"))
DIRS := $(sort $(dir $(SRC)))
# Then look for their content
define get-module-source
SRC_$1 := $(basename $(shell find $(SRCDIR)/$1 \
-maxdepth 1 -mindepth 1 -type f -name "*.[cs]" -printf "%P\n" | sort))
endef
$(foreach mod,$(MODULES), \
$(eval $(call get-module-source,$(mod))))
# Look up the includes
INCPUB := $(shell find $(INCDIR) -name "*.h" -and \
-not -path "*internals*" -printf "%P\n")
#******************************************************************************#
# Look for headers #
#******************************************************************************#
# Public headers only (not internals.h or internals/**/*.h)
INCPUB := $(shell find $(INCDIR) \
-name "*.h" -and -not -path "*internals*" -printf "%P\n" | sort)
# ... and for headers (dependencies)
# Look up the includes
INC := $(shell find $(INCDIR) -name "*.h")
#******************************************************************************#

View File

@ -17,20 +17,10 @@
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
*
* BCD are the main number format CASIO uses in its calculators.
* Each semi-byte is a digit going from 0 to 9 (0xA to 0xF aren't used).
* This format has the huge advantage to make 0.1 + 0.2 and 0.3 equal.
*
* The first three digits are the exponent.
* If the exponent is more than 500, then remove 500, and that means the
* number is negative.
* Then you have to remove 100 to have the real exponent.
*
* Before applying these operations, you should check the most significant bit
* of the upper nibble of the first binary-coded digit of the exponent.
* If it is 1, then the number has a complex part. Anyway, always set this
* bit to zero before interpreting the exponent.
*
* The other 15 digits are the mantissa. So the number is: (M ** (E + 1))
* There are several raw BCD formats, libg1m offers conversion to its own
* format, easier to read and write (but not optimized for storing).
* ************************************************************************** */
#ifndef LIBG1M_BCD_H
# define LIBG1M_BCD_H

View File

@ -41,6 +41,7 @@ typedef int (*g1m_buffer_announce_t)(void*, uint_fast32_t size);
/* ... and the structure of a buffer. */
typedef struct {
void *cookie;
size_t _offset;
g1m_buffer_read_t read;
g1m_buffer_write_t write;

View File

@ -19,7 +19,6 @@
#ifndef LIBG1M_FORMAT_H
# define LIBG1M_FORMAT_H
# include <stdint.h>
# pragma pack(1)
/* Welcome on this new episode of the Monster Circus show! Today we'll present
* to you the different formats surrounding CASIO calculators: open or closed,
@ -52,7 +51,7 @@
/* Followed by loads of zero, then, the content. The description of the rest
* of the format is described in this header: */
# include <libg1m/format/fxi.h>
//# include <libg1m/format/fxi.h>
/* ************************************************************************** */
/* The G1M format */
/* ************************************************************************** */
@ -77,6 +76,8 @@
* The LSB is the Least Significant Byte: once adapted to the host endianness,
* it can simply be obtained by bitwise-AND-ing with 0xff. */
# pragma pack(1)
struct standard_header {
/* the file identifier */
uint8_t main_id[8];

View File

@ -0,0 +1,92 @@
/* *****************************************************************************
* libg1m/format/fxi.h -- the FXI file format description.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_FXI_H
# define LIBG1M_FORMAT_FXI_H
# include <libg1m.h>
# include <stdint.h>
# pragma pack(1)
/* FXI is obfuscated with a symetrical obfuscation algorithm:
* byte = byte ^ ~24;
*
* Once the format is deobfuscated, this is the header structure: */
struct fxi_header {
/* unknown - probably part of the magic? "\xD5\xD7\x1F" "f" */
uint8_t _unknown[4];
/* description: the description of the format (probably part of the
* magic too): "FX-INTERFACE - YELLOW COMPUTING" */
char description[31];
uint8_t _unused[40];
/* the number of meta entries */
uint8_t num;
uint8_t _unused2[80];
/* sum of the number of meta entries and records */
uint16_t sum;
uint8_t _unused3;
/* 0xFF, 0xFF, 0, 0, 0x0F, 0 */
uint8_t _blackmagic[6];
/* board type? CY */
uint8_t board[2];
/* introduction? */
uint8_t type[11];
};
/* Then come the meta-entries, which have this structure: */
struct fxi_entry {
/* entry type: first type is 'NP', then {0x01, 0x80}. */
uint8_t type[2];
uint8_t _unused[2];
/* entry number */
uint8_t number;
uint8_t _unused2[3];
/* unknown: either 0x00, 0x01, 0x02 */
uint8_t _unknown;
uint8_t _unused3;
/* unknown: either 0x00, 0x02, 0x03 */
uint8_t _unknown2;
uint8_t _unused4;
/* unknown: checksum? */
uint16_t checksum;
uint8_t _unused5[2];
/* unknown: some sort of type? */
uint8_t typeid;
uint8_t _unused6;
/* size of the file name */
uint8_t filename_size;
/* TODO: finish me */
};
# pragma pack()
#endif

View File

@ -25,6 +25,7 @@
# include <libg1m.h>
# include <libg1m/formatutils.h>
# include <libg1m/internals/log.h>
# include <stdlib.h>
# include <string.h>
# include <libg1m/internals/endian.h>
@ -53,52 +54,122 @@
/* ************************************************************************** */
/* Macros and functions for parsing */
/* ************************************************************************** */
/* read with EOF check */
#define READ(TO, SZ) { \
/* read from buffer */
# define READ(TO, SZ) /* normal read */ { \
int READ_err = (*buffer->read)(buffer->cookie, (void*)(TO), (SZ)); \
buffer->_offset += SZ; \
if (READ_err) return (READ_err); }
#define GREAD(TO, SZ) { \
# define FREAD(TO, SZ) /* fail-less read */ \
err = (*buffer->read)(buffer->cookie, (void*)(TO), (SZ)); \
buffer->_offset += SZ;
# define GREAD(TO, SZ) /* read with goto fail */ { \
if ((err = (*buffer->read)(buffer->cookie, (void*)(TO), (SZ)))) \
goto fail; }
/* read with EOF check, declare var before */
#define DREAD(NAM, STRUCT) \
goto fail; \
buffer->_offset += SZ; }
/* read from buffer, declare var before */
# define DREAD(NAM, STRUCT) /* D read (I don't remember where D comes from) */ \
struct STRUCT NAM; \
READ(&NAM, sizeof(struct STRUCT))
#define GDREAD(NAM, STRUCT) \
# define GDREAD(NAM, STRUCT) /* D read with goto fail */ \
struct STRUCT NAM; \
GREAD(&NAM, sizeof(struct STRUCT))
/* read from buffer, declare tab before */
# define TREAD(NAM, TYPE, NUM) /* Tableau (list) read */ \
TYPE NAM[NUM]; \
READ(NAM, sizeof(TYPE))
/* skip */
#define SKIP(SZ) { \
# define SKIP(SZ) { \
int SKIP_err = g1m_skip(buffer, SZ, NULL); \
if (SKIP_err) return (SKIP_err); \
}
/* ************************************************************************** */
/* Specific decoding functions */
/* Memory buffer-related */
/* ************************************************************************** */
typedef int (g1m_decode_function)(g1m_t*, g1m_buffer_t*,
struct standard_header*);
/* Structure */
typedef struct {
const unsigned char *p;
size_t left;
} g1m_cursor_t;
/* types */
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;
/* Callbacks */
int g1m_membuffer_read(void *cookie, unsigned char *dest, size_t size);
/* independant functions */
/* Management functions */
int g1m_empty_limbuffer(g1m_buffer_t *limbuffer);
/* Initialize a memory buffer */
# define MEMBUFFER(P, SZ) (g1m_buffer_t){ \
.cookie = (g1m_cursor_t[]){{.p = (P), .left = (SZ)}}, \
.read = g1m_membuffer_read}
/* ************************************************************************** */
/* Limited buffer */
/* ************************************************************************** */
/* Structure */
typedef struct {
g1m_buffer_t *buffer;
size_t left;
} g1m_limited_t;
/* Callbacks */
int g1m_limbuffer_read(void *cookie, unsigned char *dest, size_t size);
/* Initialize a limited buffer */
# define LIMBUFFER(BUFFER, SZ) (g1m_buffer_t){ \
.cookie = (g1m_limited_t[]){{.buffer = (BUFFER), .left = (SZ)}}, \
.read = g1m_limbuffer_read}
/* ************************************************************************** */
/* Decoding functions */
/* ************************************************************************** */
int g1m_decode_std(g1m_t *handle, const char *path, g1m_buffer_t *buffer,
struct standard_header*, g1m_type_t expected_types);
int g1m_decode_cas(g1m_t *handle, g1m_buffer_t *buffer,
g1m_type_t expected_types);
/* ************************************************************************** */
/* "Std"-specific decoding functions */
/* ************************************************************************** */
# define G1M_STDFUNC(NAME) \
int g1m_decode_std_##NAME(g1m_t *handle, g1m_buffer_t *buffer, \
struct standard_header *std);
G1M_STDFUNC(g3p)
G1M_STDFUNC(c2p)
G1M_STDFUNC(mcs)
G1M_STDFUNC(eact)
G1M_STDFUNC(addin)
G1M_STDFUNC(addin_cg)
G1M_STDFUNC(lang)
G1M_STDFUNC(lang_cg)
G1M_STDFUNC(fkey)
G1M_STDFUNC(storage)
/* others */
int g1m_decode_fkey_cg_content(g1m_t *handle, g1m_buffer_t *buffer,
uint_fast32_t zonesize, uint32_t *pchecksum);
/* ************************************************************************** */
/* MCS-specific decoding functions */
/* ************************************************************************** */
# define G1M_MCSFUNC(NAME) \
int g1m_decode_mcs_##NAME(g1m_mcsfile_t *handle, g1m_buffer_t *buffer, \
uint_fast32_t length);
G1M_MCSFUNC(alphamem)
G1M_MCSFUNC(list)
G1M_MCSFUNC(matrix)
G1M_MCSFUNC(picture)
G1M_MCSFUNC(capture)
G1M_MCSFUNC(program)
G1M_MCSFUNC(setup)
G1M_MCSFUNC(spreadsheet)
G1M_MCSFUNC(string)
/* ************************************************************************** */
/* Picture utilities */
/* ************************************************************************** */
@ -144,7 +215,4 @@ 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);
/* Callbacks */
int g1m_membuffer_read(void *cookie, unsigned char *dest, size_t size);
#endif /* LIBG1M_INTERNALS_H */

View File

@ -50,7 +50,8 @@ typedef unsigned int g1m_mcstype_t;
/* Macros to check if the type uses the ID, and to interact with it */
# define g1m_mcstype_uses_id(T) ((T) & (\
g1m_mcstype_list | g1m_mcstype_mat | g1m_mcstype_vct | \
g1m_mcstype_pict | g1m_mcstype_capt | g1m_mcstype_string))
g1m_mcstype_pict | g1m_mcstype_capt | g1m_mcstype_string | \
g1m_mcstype_variable))
# define g1m_get_id_major(I) ((I) >> 5)
# define g1m_get_id_minor(I) ((I) & 31)
@ -103,6 +104,7 @@ typedef struct g1m_mcsfile_s {
g1m_mcs_cell_t **cells;
/* variables */
int count;
g1m_mcs_cell_t *vars;
/* for pictures and captures */

51
src/core/decode.c Normal file
View File

@ -0,0 +1,51 @@
/* *****************************************************************************
* core/decode.c -- decode a file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* g1m_decode:
* Decode a 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 buffer the buffer to read from.
* @arg expected_types the expected types.
* @return the error code (0 if ok).
*/
int g1m_decode(g1m_t *handle, const char *path, g1m_buffer_t *buffer,
g1m_type_t expected_types)
{
/* initialize the handle */
bzero(handle, sizeof(g1m_t));
/* identify a CAS file */
unsigned char buf[0x20]; READ(buf, 1)
if (buf[0] == ':')
return (g1m_decode_cas(handle, buffer, expected_types));
/* identify a standard header (send a _copy_) */
READ(&buf[1], 0x1F)
uint8_t altbuf[0x20]; memcpy(altbuf, buf, 0x20);
return (g1m_decode_std(handle, path, buffer,
(struct standard_header*)altbuf, expected_types));
}

View File

@ -61,6 +61,8 @@ int g1m_decode_casfile_head(g1m_mcshead_t *head, const char *datatype,
return (0);
}
/* TODO: g1m_decode_casfile */
/* ************************************************************************** */
/* File decoding function */
/* ************************************************************************** */

View File

@ -56,9 +56,9 @@ static void obf(unsigned char *s, size_t n)
/* File header */
/* ************************************************************************** */
static unsigned char header =
"\xD5\xD7\x1F" "f" "FX-INTERFACE - YELLOW COMPUTING"
"\xD5\xD7\x1F" "f" "FX-INTERFACE - YELLOW COMPUTING" /* 35 */
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" /* 20 */
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\x06"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
@ -121,7 +121,7 @@ static unsigned char header =
"\x01" /* number of records? */ "\x00"
"\x01\x80\0\0" "\x00" "\0\0\0" "\x02\0" "\x01\0"
"\xBA\x1E" "\0\0\x22" "\0" "\x08" /* >program name size */
"\xBA\x1E" "\0\0\x22" "\0\x08" /* >program name size */
"SpeedSnk" "\x83\x80" "\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0" "SpeedSnk"

View File

@ -1,812 +0,0 @@
/* *****************************************************************************
* decode/mcs.c -- decode an MCS archive file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
#include <stdlib.h>
/* ************************************************************************** */
/* Internal functions */
/* ************************************************************************** */
/**
* get_image:
* Allocate space, and convert monochromic image to 0x0RGB.
*
* @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(g1m_buffer_t *buffer, uint32_t ***img,
unsigned int width, unsigned int height)
{
/* get raw pixels */
size_t linesize = width / 8 + !!(width % 8);
size_t bufsize = height * linesize;
uint8_t buf[bufsize];
READ(buf, bufsize)
/* alloc */
*img = malloc(height * (sizeof(uint32_t*))
+ width * height * sizeof(uint32_t));
if (!*img)
return (g1m_error_alloc);
/* fill */
uint32_t **image = *img;
for (uint_fast16_t y = 0; y < height; y++) {
/* setup index */
image[y] = (uint32_t*)&image[height] + y * width;
/* init vars for monochrome with fill bits image browsing */
uint8_t *b = &buf[y * linesize];
int bit = 1 << 7;
/* browse and save pixels! (monochrome to 0x0RGB) */
for (uint_fast16_t x = 0; x < width; x++) {
/* set pixel */
image[y][x] = *b & bit ? 0xffffff : 0x000000;
/* go further */
b += bit & 1;
bit = (bit >> 1) | ((bit & 1) << 7);
}
}
/* no error */
return (0);
}
/* ************************************************************************** */
/* MCS file parsing */
/* ************************************************************************** */
/**
* mcs_decode_program:
* Decode a program.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_decode_program(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read header */
DREAD(hd, mcs_programheader)
/* print header data */
log_info("Program password is '%.8s'.", hd.password);
/* store info */
strncpy(handle->password, (char*)hd.password, 8);
handle->password[8] = 0;
/* get content */
size_t content_size = length - sizeof(struct mcs_programheader);
log_info("Getting program content (%" PRIuSIZE "o)", content_size);
handle->content = malloc(content_size + 1);
handle->head.size = content_size + 1;
if (!handle->content) return (g1m_error_alloc);
READ(handle->content, content_size);
handle->content[content_size] = 0;
/* no error */
return (0);
}
/**
* mcs_decode_spreadsheet:
* Decode a spreadsheet.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_decode_spreadsheet(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read header */
DREAD(hd, mcs_spreadsheetheader)
/* check if the spreadsheet type is known */
if (hd.has_subheader != 0x01)
return (0);
/* read subheader */
DREAD(shd, mcs_spreadsheet_subheader)
/* correct endianness */
uint_fast32_t colcount = hd.column_count;
colcount = be32toh(colcount << 8);
shd.defs_size = be32toh(shd.defs_size);
/* prepare */
g1m_mcs_cell_t cells[1000 * colcount];
bzero(cells, sizeof(g1m_mcs_cell_t) * 1000 * colcount);
int cells_count = 0;
uint_fast32_t rows = 0;
uint_fast32_t cols = 0;
/* log some info */
log_info("%" PRIuFAST32 " columns to read!", colcount);
if (colcount) {
/* get the column directory */
uint32_t column_directory[colcount];
READ(&column_directory, sizeof(uint32_t) * colcount)
/* browse columns */
for (uint_fast32_t c = 0; c < colcount; c++) {
/* check if column is empty */
if (!column_directory[c])
continue;
/* get the row directory */
uint8_t row_directory[0x80];
READ(&row_directory, (size_t)0x80)
/* initialize loop values */
uint8_t *rd = row_directory;
int bit = 1 << 7;
/* explore each cell */
for (uint_fast32_t i = 0; i < 1000; i++) {
/* check if used */
if (*rd & bit) {
/* get cell */
g1m_bcd_t cell;
DREAD(rawcell, bcd)
g1m_bcd_frommcs(&rawcell, &cell);
/* store it */
cells[c * 1000 + i] = (g1m_mcs_cell_t){
.used = 1,
.real = cell,
.imgn = (g1m_bcd_t){}
};
/* check things (max row, max col, cells count) */
rows = max(rows, i);
cols = c;
cells_count++;
}
/* iterate bit and rd */
rd += (bit & 1);
bit = (bit >> 1) | ((bit & 1) << 7);
}
}
}
/* we have max rows and columns, increment to have sizes */
rows++, cols++;
/* create final tab */
handle->cells = NULL;
handle->columns = 0;
handle->rows = 0;
if (cells_count) {
handle->columns = cols;
handle->rows = rows;
/* alloc */
g1m_mcs_cell_t **tab = malloc(sizeof(g1m_mcs_cell_t*) * cols);
if (!tab) return (g1m_error_alloc);
g1m_mcs_cell_t *rws = malloc(sizeof(g1m_mcs_cell_t) * cols * rows);
if (!rws) { free(tab); return (g1m_error_alloc); }
/* main copying loop */
for (uint_fast32_t y = 0; y < cols; y++) {
/* prepare index */
tab[y] = &rws[y * rows];
/* copy each cell */
for (uint_fast32_t x = 0; x < rows; x++)
tab[y][x] = cells[x * 1000 + y];
}
/* i used to be a cow. */
handle->cells = tab;
}
/* no error */
return (0);
}
/**
* mcs_decode_list:
* Decode an List.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg size the length.
* @return the error code (0 if ok).
*/
static int mcs_decode_list(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t size)
{
/* read header */
DREAD(hd, mcs_listheader)
/* correct endianess */
uint_fast16_t elcount = be16toh(hd.element_count);
/* log */
log_info("Title is '%.8s'", hd.title);
/* prepare browsing */
size -= sizeof(struct mcs_listheader);
/* make tabs */
g1m_bcd_t real[elcount], imgn[elcount];
if (elcount) {
int one_imgn = 0;
mcs_bcd_t tab[elcount];
/* read the real parts */
size_t elsize = sizeof(mcs_bcd_t) * elcount;
size -= elsize; {
/* read reals */
READ(tab, elsize)
/* convert them */
for (uint_fast16_t i = 0; i < elsize; i++)
one_imgn |= g1m_bcd_frommcs(&tab[elcount], &real[elcount]);
}
/* read the imaginary parts */
if (one_imgn) {
READ(tab, elsize)
/* convert */
for (uint_fast16_t i = 0; i < elsize; i++)
g1m_bcd_frommcs(&tab[elcount], &imgn[elcount]);
}
}
/* fill final tab */
handle->rows = elcount;
handle->columns = 1;
handle->cells = NULL;
if (elcount) {
/* allocate final tab */
g1m_mcs_cell_t **tab = malloc(sizeof(g1m_mcs_cell_t*) * elcount);
if (!tab) return (g1m_error_alloc);
g1m_mcs_cell_t *rws = malloc(sizeof(g1m_mcs_cell_t) * elcount);
if (!tab) { free(tab); return (g1m_error_alloc); }
/* main copying loop */
for (uint_fast32_t y = 0; y < elcount; y++) {
int has_complex = g1m_bcd_has_special(&real[y]);
/* prepare index and store */
tab[y] = &rws[y];
tab[y][0] = (g1m_mcs_cell_t){
.used = 1,
.real = real[y],
.imgn = has_complex ? imgn[y] : (g1m_bcd_t){}
};
}
/* don't forget your baguette! */
handle->cells = tab;
}
/* no error */
return (0);
}
/**
* mcs_decode_matrix:
* Decode a matrix.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_decode_matrix(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
g1m_mcs_cell_t **tab, *rws;
int err = g1m_error_alloc;
/* read header */
DREAD(hd, mcs_matheader)
/* correct endianess */
hd.width = be16toh(hd.width);
hd.height = be16toh(hd.height);
/* log info */
uint_fast32_t w = hd.width, h = hd.height;
log_info("Matrix size is %" PRIuFAST32 "*%" PRIuFAST32, w, h);
/* store dimensions */
handle->rows = w;
handle->columns = h;
handle->cells = NULL;
if (w && h) {
/* alloc real matrix */
tab = malloc(sizeof(g1m_mcs_cell_t*) * h);
if (!tab) return (g1m_error_alloc);
rws = malloc(sizeof(g1m_mcs_cell_t) * h * w);
if (!rws) { free(tab); return (g1m_error_alloc); }
/* copy */
int one_imgn = 0;
for (uint_fast32_t y = 0; y < h; y++) {
/* prepare index */
tab[y] = &rws[y * w];
/* read squares */
for (uint_fast32_t x = 0; x < w; x++) {
/* read the cell */
g1m_bcd_t cell;
GDREAD(rawcell, bcd)
one_imgn |= g1m_bcd_frommcs(&rawcell, &cell);
/* store it */
tab[y][x] = (g1m_mcs_cell_t){
.real = cell,
.imgn = {},
.used = 1
};
}
}
/* check imaginary parts */
if (one_imgn) {
for (uint_fast32_t y = 0; y < h; y++)
for (uint_fast32_t x = 0; x < w; x++) {
GDREAD(rawcell, bcd)
if (tab[y][x].real.spe) {
g1m_bcd_t cell;
g1m_bcd_frommcs(&rawcell, &cell);
tab[y][x].imgn = cell;
}
}
}
/* your sandwich, monsieur. */
handle->cells = tab;
}
/* no error */
return (0);
/* in case of unexpected EOF */
fail:
free(tab);
free(rws);
return (err);
}
/**
* mcs_decode_capture:
* Decode a capture.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_decode_capture(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read header */
DREAD(hd, mcs_captureheader)
/* correct endianess */
hd.width = be16toh(hd.width);
hd.height = be16toh(hd.height);
/* store */
handle->width = hd.width;
handle->height = hd.height;
/* print info */
log_info("capture is %dx%d sized", handle->width, handle->height);
/* get the image and return */
return (get_image(buffer, &handle->image, handle->width, handle->height));
}
/**
* mcs_decode_picture:
* Decode a picture.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_decode_picture(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
int err;
/* store some dimensions, in case. */
handle->width = 128;
handle->height = 64;
/* get the first image */
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(buffer, &handle->second_image, 128, 64))) {
log_fatal("Failed to get the second image.");
return (err);
}
/* no error */
return (0);
}
/**
* mcs_decode_string:
* Decode an MCS string.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_decode_string(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
(void)handle;
log_info("String MCS file is not managed yet. Content:");
uint8_t str[length];
READ(str, length);
logm_info(str, length);
/* TODO */
return (0);
}
/**
* mcs_decode_setup:
* Decode settings.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_decode_setup(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
(void)handle;
log_info("Settings MCS file is not managed yet.");
/* TODO */
SKIP(length)
return (0);
}
/**
* mcs_decode_alphamem:
* Decode alpha memory (variables).
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
static int mcs_decode_alphamem(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read the data */
uint8_t buf[length];
READ(buf, length)
/* allocate the vars table */
handle->vars = malloc(29 * sizeof(g1m_mcs_cell_t));
if (!handle->vars) return (g1m_error_alloc);
bzero(handle->vars, 29 * sizeof(g1m_mcs_cell_t));
/* copy */
size_t tocopy = length - length % sizeof(g1m_mcs_cell_t);
memcpy(handle->vars, buf, tocopy);
/* no problem, woop woop */
return (0);
}
/* ************************************************************************** */
/* Type correspondance list */
/* ************************************************************************** */
/* MCS file parsing function type */
typedef int (*mcs_decode_func_t)(g1m_mcsfile_t*, g1m_buffer_t*, uint_fast32_t);
/* Correspondance type */
struct mcs_corresp {
unsigned int type;
mcs_decode_func_t decode;
};
/* All correspondances */
static struct mcs_corresp mcs_types[] = {
{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_decode:
* Lookup for a parsing function for an MCS file type.
*
* @arg type the libg1m MCS file type.
* @return the function (NULL if not found).
*/
static mcs_decode_func_t lookup_mcsfile_decode(unsigned int type)
{
/* lookup for the type */
struct mcs_corresp *c = mcs_types;
while (c->decode) {
if (type == c->type)
break;
c++;
}
/* return the function */
return (c->decode);
}
/* ************************************************************************** */
/* Public file functions */
/* ************************************************************************** */
/**
* g1m_decode_mcsfile_head:
* Decode MCS file head.
*
* @arg head the head to fill.
* @arg raw_type the raw file type.
* @arg groupname the groupname (up to 16 bytes).
* @arg dirname the directory name (up to 8 bytes).
* @arg filename the filename (up to 8 bytes).
* @arg filesize the data length.
* @return 0 if the head was filled with success, -1 otherwise.
*/
int g1m_decode_mcsfile_head(g1m_mcshead_t *head,
int raw_type, const unsigned char *groupname,
const unsigned char *dirname, const unsigned char *filename,
uint_fast32_t filesize)
{
/* check that we have a head, lol */
if (!head) return (-1);
/* look for the raw type */
if (g1m_mcstype_get((char*)groupname, (char*)filename, raw_type,
&head->type, &head->id))
head->type = g1m_mcstype_unknown;
log_info("libg1m file type is 0x%04X", head->type);
#if LOGLEVEL <= ll_info
if (g1m_mcstype_uses_id(head->type)) {
log_info("libg1m file id is (%d, %d)", g1m_get_id_major(head->id),
g1m_get_id_minor(head->id));
}
#endif
/* copy the name and size */
memcpy(head->name, filename, 8); head->name[8] = 0;
head->size = filesize;
/* save raw data */
head->_rawtype = raw_type;
memcpy(head->_group, groupname, 16); head->_group[16] = 0;
if (dirname) {
memcpy(head->_dirname, dirname, 8); head->_dirname[8] = 0;
} else memset(head->_dirname, 0, 9);
/* everything went well! */
return (0);
}
/**
* g1m_decode_mcsfile:
* Decode MCS file content.
*
* Part of the public API because of the Protocol 7, where file is sent
* without its header (only with specific subheaders).
*
* @arg handle the handle to make.
* @arg head the head to use.
* @arg buffer the buffer to read from.
* @return the error code (0 if ok).
*/
int g1m_decode_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *head,
g1m_buffer_t *buffer)
{
int err = 0;
/* check that the head is there */
if (!head) return (g1m_error_op);
/* create handle */
*handle = malloc(sizeof(g1m_mcsfile_t));
if (!handle) return (g1m_error_alloc);
g1m_mcsfile_t *h = *handle;
memset(h, 0, sizeof(g1m_mcsfile_t));
/* copy the head */
memcpy(&h->head, head, sizeof(g1m_mcshead_t));
/* look for the parsing function */
mcs_decode_func_t decode = lookup_mcsfile_decode(head->type);
if (!decode) {
log_error("No dedicated parsing function for this type was found!");
goto notparsing;
}
/* decode */
err = (*decode)(h, buffer, head->size);
if (err) goto fail;
/* no error :D */
return (0);
notparsing:
/* allocate enough space */
h->content = malloc(head->size);
err = g1m_error_alloc;
if (!h->content) goto fail;
/* read the content */
GREAD(h->content, head->size)
/* log */
log_info("File content:");
logm_info(h->content, head->size);
/* saved normally */
return (0);
fail:
if (h) {
if (h->content) free(h->content);
free(h);
}
*handle = NULL;
return (err);
}
/**
* g1m_decode_mcsfile_data:
* Decode a MCS file content from raw memory.
*
* @arg handle the file handle.
* @arg head the file head.
* @arg data the buffer data.
* @arg size the buffer size.
* @return the libg1m error.
*/
int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle,
const g1m_mcshead_t *head, const unsigned char *data, size_t size)
{
const unsigned char *p = data;
g1m_buffer_t buffer = {
.cookie = p,
.read = g1m_membuffer_read
};
return (g1m_decode_mcsfile(handle, head, &buffer));
}
/* ************************************************************************** */
/* Main file function */
/* ************************************************************************** */
/**
* g1m_decode_mcs:
* Decode an MCS file, after the Standard Header.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg num number of sizes.
* @return the error code (0 if ok).
*/
int g1m_decode_mcs(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
int err = g1m_error_alloc;
/* get number of subparts from the standard header */
uint_fast16_t num = std->number;
/* allocate memory for the files index */
handle->count = 0;
handle->_size = num;
if (num) {
handle->files = malloc(sizeof(g1m_mcsfile_t*) * num);
if (!handle->files) return (g1m_error_alloc);
}
/* read all of the parts */
log_info("%" PRIuFAST16 " total mcs files to browse", num);
while (handle->count < (int)num) {
/* get the subheader */
GDREAD(hd, mcs_subheader)
/* correct endianess */
hd.subcount = be32toh(hd.subcount);
/* log info about part */
log_info("New group! Group name is '%.16s'.", hd.intname);
log_info("%d mcs files to browse in that group", hd.subcount);
/* foreach subpart */
for (uint_fast32_t i = 0; i < hd.subcount; i++) {
/* get the part header */
GDREAD(fhd, mcs_fileheader)
/* correct endianess */
fhd.datalength = be32toh(fhd.datalength);
/* log info about the subpart */
log_info("[%" PRIuFAST32 "] directory name is '%.8s'",
i, fhd.dirname);
log_info("[%" PRIuFAST32 "] filename is '%.8s'", i, fhd.filename);
log_info("[%" PRIuFAST32 "] data length is %" PRIu32,
i, fhd.datalength);
/* decode the head */
g1m_mcshead_t head;
g1m_decode_mcsfile_head(&head, fhd.filetype, hd.intname,
fhd.dirname, fhd.filename, fhd.datalength);
/* decode */
handle->files[handle->count] = NULL;
err = g1m_decode_mcsfile(&handle->files[handle->count],
&head, buffer);
if (err) goto fail;
handle->count++;
}
}
/* no error */
return (0);
/* was error! */
fail:
g1m_free_mcs(handle);
return (err);
}

59
src/decode/mcs/alphamem.c Normal file
View File

@ -0,0 +1,59 @@
/* *****************************************************************************
* decode/mcs/alphamem.c -- decode an MCS alpha memory file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* g1m_decode_mcs_alphamem:
* Decode alpha memory (variables).
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
int g1m_decode_mcs_alphamem(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read the data */
uint8_t buf[length];
READ(buf, length)
/* count number of vars */
handle->count = length / (2 * sizeof(mcs_bcd_t));
/* allocate the vars table */
handle->vars = malloc(handle->count * sizeof(g1m_mcs_cell_t));
if (!handle->vars) return (g1m_error_alloc);
/* copy */
const mcs_bcd_t *b = (void*)buf;
for (int i = 0; i < handle->count; i++) {
g1m_bcd_frommcs(b++, &handle->vars[i].real);
g1m_bcd_frommcs(b++, &handle->vars[i].imgn);
handle->vars[i].used = 1;
}
/* copy */
size_t tocopy = length - length % sizeof(g1m_mcs_cell_t);
memcpy(handle->vars, buf, tocopy);
/* no problem, woop woop */
return (0);
}

102
src/decode/mcs/list.c Normal file
View File

@ -0,0 +1,102 @@
/* *****************************************************************************
* decode/mcs/list.c -- decode an MCS list.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* g1m_decode_mcs_list:
* Decode an List.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg size the length.
* @return the error code (0 if ok).
*/
int g1m_decode_mcs_list(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t size)
{
/* read header */
DREAD(hd, mcs_listheader)
/* correct endianess */
uint_fast16_t elcount = be16toh(hd.element_count);
/* log */
log_info("Title is '%.8s'", hd.title);
/* prepare browsing */
size -= sizeof(struct mcs_listheader);
/* make tabs */
g1m_bcd_t real[elcount], imgn[elcount];
if (elcount) {
int one_imgn = 0;
mcs_bcd_t tab[elcount];
/* read the real parts */
size_t elsize = sizeof(mcs_bcd_t) * elcount;
size -= elsize; {
/* read reals */
READ(tab, elsize)
/* convert them */
for (uint_fast16_t i = 0; i < elsize; i++)
one_imgn |= g1m_bcd_frommcs(&tab[elcount], &real[elcount]);
}
/* read the imaginary parts */
if (one_imgn) {
READ(tab, elsize)
/* convert */
for (uint_fast16_t i = 0; i < elsize; i++)
g1m_bcd_frommcs(&tab[elcount], &imgn[elcount]);
}
}
/* fill final tab */
handle->rows = elcount;
handle->columns = 1;
handle->cells = NULL;
if (elcount) {
/* allocate final tab */
g1m_mcs_cell_t **tab = malloc(sizeof(g1m_mcs_cell_t*) * elcount);
if (!tab) return (g1m_error_alloc);
g1m_mcs_cell_t *rws = malloc(sizeof(g1m_mcs_cell_t) * elcount);
if (!tab) { free(tab); return (g1m_error_alloc); }
/* main copying loop */
for (uint_fast32_t y = 0; y < elcount; y++) {
int has_complex = g1m_bcd_has_special(&real[y]);
/* prepare index and store */
tab[y] = &rws[y];
tab[y][0] = (g1m_mcs_cell_t){
.used = 1,
.real = real[y],
.imgn = has_complex ? imgn[y] : (g1m_bcd_t){}
};
}
/* don't forget your baguette! */
handle->cells = tab;
}
/* no error */
return (0);
}

106
src/decode/mcs/matrix.c Normal file
View File

@ -0,0 +1,106 @@
/* *****************************************************************************
* decode/mcs/matrix.c -- decode an MCS matrix.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* g1m_decode_mcs_matrix:
* Decode a matrix.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
int g1m_decode_mcs_matrix(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
g1m_mcs_cell_t **tab, *rws;
int err = g1m_error_alloc;
/* read header */
DREAD(hd, mcs_matheader)
/* correct endianess */
hd.width = be16toh(hd.width);
hd.height = be16toh(hd.height);
/* log info */
uint_fast32_t w = hd.width, h = hd.height;
log_info("Matrix size is %" PRIuFAST32 "*%" PRIuFAST32, w, h);
/* store dimensions */
handle->rows = w;
handle->columns = h;
handle->cells = NULL;
if (w && h) {
/* alloc real matrix */
tab = malloc(sizeof(g1m_mcs_cell_t*) * h);
if (!tab) return (g1m_error_alloc);
rws = malloc(sizeof(g1m_mcs_cell_t) * h * w);
if (!rws) { free(tab); return (g1m_error_alloc); }
/* copy */
int one_imgn = 0;
g1m_bcd_t bcd;
for (uint_fast32_t y = 0; y < h; y++) {
/* prepare index */
tab[y] = &rws[y * w];
/* read squares */
for (uint_fast32_t x = 0; x < w; x++) {
/* read the cell */
GDREAD(rawbcd, bcd)
one_imgn |= g1m_bcd_frommcs(&rawbcd, &bcd);
/* store it */
tab[y][x] = (g1m_mcs_cell_t){
.real = bcd,
.imgn = {},
.used = 1
};
}
}
/* check imaginary parts */
if (one_imgn) {
for (uint_fast32_t y = 0; y < h; y++)
for (uint_fast32_t x = 0; x < w; x++) {
GDREAD(rawbcd, bcd)
if (tab[y][x].real.spe) {
g1m_bcd_frommcs(&rawbcd, &bcd);
tab[y][x].imgn = bcd;
}
}
}
/* your sandwich, monsieur. */
handle->cells = tab;
}
/* no error */
return (0);
/* in case of unexpected EOF */
fail:
free(tab);
free(rws);
return (err);
}

141
src/decode/mcs/picture.c Normal file
View File

@ -0,0 +1,141 @@
/* *****************************************************************************
* decode/mcs/picture.c -- decode an MCS picture.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/* ************************************************************************** */
/* Internal functions */
/* ************************************************************************** */
/**
* get_image:
* Allocate space, and convert monochromic image to 0x0RGB.
*
* @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(g1m_buffer_t *buffer, uint32_t ***img,
unsigned int width, unsigned int height)
{
/* get raw pixels */
size_t linesize = width / 8 + !!(width % 8);
size_t bufsize = height * linesize;
uint8_t buf[bufsize];
READ(buf, bufsize)
/* alloc */
*img = malloc(height * (sizeof(uint32_t*))
+ width * height * sizeof(uint32_t));
if (!*img)
return (g1m_error_alloc);
/* fill */
uint32_t **image = *img;
for (uint_fast16_t y = 0; y < height; y++) {
/* setup index */
image[y] = (uint32_t*)&image[height] + y * width;
/* init vars for monochrome with fill bits image browsing */
uint8_t *b = &buf[y * linesize];
int bit = 1 << 7;
/* browse and save pixels! (monochrome to 0x0RGB) */
for (uint_fast16_t x = 0; x < width; x++) {
/* set pixel */
image[y][x] = *b & bit ? 0xffffff : 0x000000;
/* go further */
b += bit & 1;
bit = (bit >> 1) | ((bit & 1) << 7);
}
}
/* no error */
return (0);
}
/* ************************************************************************** */
/* Real decode functions */
/* ************************************************************************** */
/**
* g1m_decode_mcs_capture:
* Decode a capture.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
int g1m_decode_mcs_capture(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read header */
DREAD(hd, mcs_captureheader)
/* correct endianess */
hd.width = be16toh(hd.width);
hd.height = be16toh(hd.height);
/* store */
handle->width = hd.width;
handle->height = hd.height;
/* print info */
log_info("capture is %dx%d sized", handle->width, handle->height);
/* get the image and return */
return (get_image(buffer, &handle->image, handle->width, handle->height));
}
/**
* g1m_decode_mcs_picture:
* Decode a picture.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
int g1m_decode_mcs_picture(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
int err;
/* store some dimensions, in case. */
handle->width = 128;
handle->height = 64;
/* get the first image */
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(buffer, &handle->second_image, 128, 64))) {
log_fatal("Failed to get the second image.");
return (err);
}
/* no error */
return (0);
}

55
src/decode/mcs/program.c Normal file
View File

@ -0,0 +1,55 @@
/* *****************************************************************************
* decode/mcs/program.c -- decode an MCS program.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* g1m_decode_mcs_program:
* Decode a program.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
int g1m_decode_mcs_program(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read header */
DREAD(hd, mcs_programheader)
/* print header data */
log_info("Program password is '%.8s'.", hd.password);
/* store info */
strncpy(handle->password, (char*)hd.password, 8);
handle->password[8] = 0;
/* get content */
size_t content_size = length - sizeof(struct mcs_programheader);
log_info("Getting program content (%" PRIuSIZE "o)", content_size);
handle->content = malloc(content_size + 1);
handle->head.size = content_size + 1;
if (!handle->content) return (g1m_error_alloc);
READ(handle->content, content_size);
handle->content[content_size] = 0;
/* no error */
return (0);
}

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* libg1m/format/fxi.h -- the FXI file format description.
* decode/mcs/setup.c -- decode an MCS setup file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -16,13 +16,24 @@
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_FXI_H
# define LIBG1M_FORMAT_FXI_H
# include <libg1m.h>
# include <stdint.h>
# pragma pack(1)
#include <libg1m/internals.h>
/* TODO, I guess? */
/**
* g1m_decode_mcs_setup:
* Decode settings.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
# pragma pack()
#endif
int g1m_decode_mcs_setup(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
(void)handle;
log_info("Settings MCS file is not managed yet.");
/* TODO */
SKIP(length)
return (0);
}

View File

@ -0,0 +1,140 @@
/* *****************************************************************************
* decode/mcs/spreadsheet.c -- decode an MCS spreadsheet.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* g1m_decode_mcs_spreadsheet:
* Decode a spreadsheet.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
int g1m_decode_mcs_spreadsheet(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
/* read header */
DREAD(hd, mcs_spreadsheetheader)
/* check if the spreadsheet type is known */
if (hd.has_subheader != 0x01)
return (0);
/* read subheader */
DREAD(shd, mcs_spreadsheet_subheader)
/* correct endianness */
uint_fast32_t colcount = hd.column_count;
colcount = be32toh(colcount << 8);
shd.defs_size = be32toh(shd.defs_size);
/* prepare */
g1m_mcs_cell_t cells[1000 * colcount];
bzero(cells, sizeof(g1m_mcs_cell_t) * 1000 * colcount);
int cells_count = 0;
uint_fast32_t rows = 0;
uint_fast32_t cols = 0;
/* log some info */
log_info("%" PRIuFAST32 " columns to read!", colcount);
if (colcount) {
/* get the column directory */
uint32_t column_directory[colcount];
READ(&column_directory, sizeof(uint32_t) * colcount)
/* browse columns */
for (uint_fast32_t c = 0; c < colcount; c++) {
/* check if column is empty */
if (!column_directory[c])
continue;
/* get the row directory */
uint8_t row_directory[0x80];
READ(&row_directory, (size_t)0x80)
/* initialize loop values */
uint8_t *rd = row_directory;
int bit = 1 << 7;
/* explore each cell */
for (uint_fast32_t i = 0; i < 1000; i++) {
/* check if used */
if (*rd & bit) {
/* get cell */
g1m_bcd_t cell;
DREAD(rawcell, bcd)
g1m_bcd_frommcs(&rawcell, &cell);
/* store it */
cells[c * 1000 + i] = (g1m_mcs_cell_t){
.used = 1,
.real = cell,
.imgn = (g1m_bcd_t){}
};
/* check things (max row, max col, cells count) */
rows = max(rows, i);
cols = c;
cells_count++;
}
/* iterate bit and rd */
rd += (bit & 1);
bit = (bit >> 1) | ((bit & 1) << 7);
}
}
}
/* we have max rows and columns, increment to have sizes */
rows++, cols++;
/* create final tab */
handle->cells = NULL;
handle->columns = 0;
handle->rows = 0;
if (cells_count) {
handle->columns = cols;
handle->rows = rows;
/* alloc */
g1m_mcs_cell_t **tab = malloc(sizeof(g1m_mcs_cell_t*) * cols);
if (!tab) return (g1m_error_alloc);
g1m_mcs_cell_t *rws = malloc(sizeof(g1m_mcs_cell_t) * cols * rows);
if (!rws) { free(tab); return (g1m_error_alloc); }
/* main copying loop */
for (uint_fast32_t y = 0; y < cols; y++) {
/* prepare index */
tab[y] = &rws[y * rows];
/* copy each cell */
for (uint_fast32_t x = 0; x < rows; x++)
tab[y][x] = cells[x * 1000 + y];
}
/* i used to be a cow. */
handle->cells = tab;
}
/* no error */
return (0);
}

41
src/decode/mcs/string.c Normal file
View File

@ -0,0 +1,41 @@
/* *****************************************************************************
* decode/mcs/string.c.c -- decode an MCS string.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* g1m_decode_mcs_string:
* Decode an MCS string.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg length the data length.
* @return the error code (0 if ok).
*/
int g1m_decode_mcs_string(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
uint_fast32_t length)
{
(void)handle;
log_info("String MCS file is not managed yet. Content:");
uint8_t str[length];
READ(str, length);
logm_info(str, length);
/* TODO */
return (0);
}

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* decode/main.c -- decode a file.
* decode/std.c -- decode a "standard" CASIO file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -15,59 +15,58 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
*
* Actually, this file implements the general decoding function, and the
* standard header files general decoding function ("""historical""" reasons).
* ************************************************************************** */
#include <libg1m/internals.h>
#define FUNC(NAME) g1m_decode_std_##NAME
/* ************************************************************************** */
/* Getting the parsing function */
/* ************************************************************************** */
/* Correspondance type */
typedef int (*decode_func)(g1m_t*, g1m_buffer_t*, struct standard_header*);
struct corresp {
unsigned int platform;
unsigned int type;
/* result */
g1m_decode_function *decode;
decode_func decode;
};
/* The correspondances */
static struct corresp parsing_functions[] = {
/* add-ins */
{g1m_platform_fx, g1m_type_addin,
g1m_decode_addin},
FUNC(addin)},
{g1m_platform_cg, g1m_type_addin,
g1m_decode_addin_cg},
FUNC(addin_cg)},
/* mcs */
{g1m_platform_fx, g1m_type_mcs,
g1m_decode_mcs},
FUNC(mcs)},
{g1m_platform_cg, g1m_type_mcs,
g1m_decode_mcs},
FUNC(mcs)},
/* language files */
{g1m_platform_fx, g1m_type_lang,
g1m_decode_lang},
FUNC(lang)},
{g1m_platform_cg, g1m_type_lang,
g1m_decode_lang_cg},
FUNC(lang_cg)},
/* function keys file */
{g1m_platform_fx, g1m_type_fkey,
g1m_decode_fkey},
FUNC(fkey)},
{g1m_platform_cg, g1m_type_fkey,
g1m_decode_lang_cg},
FUNC(lang_cg)},
/* e-activities */
{g1m_platform_fx, g1m_type_eact,
g1m_decode_eact},
FUNC(eact)},
/* pictures */
{g1m_platform_cg, g1m_type_pict,
g1m_decode_g3p},
FUNC(g3p)},
{g1m_platform_cp, g1m_type_pict,
g1m_decode_c2p},
FUNC(c2p)},
/* storage */
/*{g1m_platform_none, g1m_type_storage,
@ -88,7 +87,7 @@ static struct corresp parsing_functions[] = {
*/
static int find_decode_function(g1m_t *handle, const char *path,
struct standard_header *std, g1m_decode_function **rd)
struct standard_header *std, decode_func *rd)
{
/* get the type */
unsigned int platform, type;
@ -134,7 +133,7 @@ static int find_decode_function(g1m_t *handle, const char *path,
/* Main standard header decoding function */
/* ************************************************************************** */
/**
* decode_std:
* g1m_decode_std:
* Decode a file with standard header.
*
* @arg handle the handle.
@ -145,7 +144,7 @@ static int find_decode_function(g1m_t *handle, const char *path,
* @return the error code (0 if ok).
*/
static int decode_std(g1m_t *handle, const char *path, g1m_buffer_t *buffer,
int g1m_decode_std(g1m_t *handle, const char *path, g1m_buffer_t *buffer,
struct standard_header *std, g1m_type_t expected_types)
{
/* reverse the standard header */
@ -162,7 +161,7 @@ static int decode_std(g1m_t *handle, const char *path, g1m_buffer_t *buffer,
std->number = be16toh(std->number);
/* get type */
g1m_decode_function *read_func; int err;
decode_func read_func; int err;
if ((err = find_decode_function(handle, path, std, &read_func)))
return (err);
@ -177,38 +176,3 @@ static int decode_std(g1m_t *handle, const char *path, g1m_buffer_t *buffer,
/* subdecode. */
return ((*read_func)(handle, buffer, std));
}
/* ************************************************************************** */
/* Main decoding function */
/* ************************************************************************** */
/**
* g1m_decode:
* Decode a 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 buffer the buffer to read from.
* @arg expected_types the expected types.
* @return the error code (0 if ok).
*/
int g1m_decode(g1m_t *handle, const char *path, g1m_buffer_t *buffer,
g1m_type_t expected_types)
{
/* initialize the handle */
bzero(handle, sizeof(g1m_t));
/* identify a CAS file */
unsigned char buf[0x20]; READ(buf, 1)
if (buf[0] == ':')
return (g1m_decode_cas(handle, buffer, expected_types));
/* identify a standard header (send a _copy_) */
READ(&buf[1], 0x1F)
uint8_t altbuf[0x20]; memcpy(altbuf, buf, 0x20);
return (decode_std(handle, path, buffer, (struct standard_header*)altbuf,
expected_types));
}

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* decode/addin.c -- decode an add-in file.
* decode/std/addin.c -- decode an add-in file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -74,7 +74,7 @@ static void addin_set_data(g1m_t *handle,
}
/**
* g1m_decode_addin:
* g1m_decode_std_addin:
* Decodes a "normal" add-in (after Standard Header).
*
* @arg handle the handle.
@ -82,7 +82,7 @@ static void addin_set_data(g1m_t *handle,
* @return the error code (0 if ok).
*/
int g1m_decode_addin(g1m_t *handle, g1m_buffer_t *buffer,
int g1m_decode_std_addin(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
int err = 0;
@ -127,7 +127,7 @@ int g1m_decode_addin(g1m_t *handle, g1m_buffer_t *buffer,
}
/**
* g1m_decode_addin_cg:
* g1m_decode_std_addin_cg:
* Decode fx-CG add-in (after Standard Header).
*
* @arg handle the handle.
@ -136,7 +136,7 @@ int g1m_decode_addin(g1m_t *handle, g1m_buffer_t *buffer,
* @return the error code (0 if ok).
*/
int g1m_decode_addin_cg(g1m_t *handle, g1m_buffer_t *buffer,
int g1m_decode_std_addin_cg(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
int err = 0;

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* decode/eact.c -- decode an e-activity file.
* decode/std/eact.c -- decode an e-activity file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -423,7 +423,7 @@ static int eact_decode_line(g1m_line_t *handle, uint8_t *buf, size_t size,
/* Main parsing functions */
/* ************************************************************************** */
/**
* g1m_decode_eact:
* g1m_decode_std_eact:
* Decodes an EACT.
*
* Thanks to Julese50 for his help on e-acts parsing.
@ -433,7 +433,7 @@ static int eact_decode_line(g1m_line_t *handle, uint8_t *buf, size_t size,
* @return the error code (0 if ok).
*/
int g1m_decode_eact(g1m_t * handle, g1m_buffer_t *buffer,
int g1m_decode_std_eact(g1m_t * handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
(void)std;

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* decode/fkey.c -- decode a function keys file.
* decode/std/fkey.c -- decode a function keys file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -61,7 +61,7 @@ static uint32_t **fkeydup3(uint8_t *fkey)
/* fx function keys file parsing utilities */
/* ************************************************************************** */
/**
* g1m_decode_fkey:
* g1m_decode_std_fkey:
* Decode fx function keys files.
*
* @arg handle the libg1m handle.
@ -70,7 +70,7 @@ static uint32_t **fkeydup3(uint8_t *fkey)
* @return the error code (0 if ok).
*/
int g1m_decode_fkey(g1m_t *handle, g1m_buffer_t *buffer,
int g1m_decode_std_fkey(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
(void)std;

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* decode/lang.c -- decode a language file.
* decode/std/lang.c -- decode a language file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -22,7 +22,7 @@
/* fx language files parsing */
/* ************************************************************************** */
/**
* g1m_decode_lang:
* g1m_decode_std_lang:
* Decode fx language files.
*
* @arg handle the libg1m handle.
@ -30,7 +30,7 @@
* @return the error code (0 if ok).
*/
int g1m_decode_lang(g1m_t *handle, g1m_buffer_t *buffer,
int g1m_decode_std_lang(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
(void)std;
@ -192,7 +192,7 @@ fail:
}
/**
* g1m_decode_lang_cg:
* g1m_decode_std_lang_cg:
* Decode fx-CG language files.
*
* @arg handle the libg1m handle.
@ -201,7 +201,7 @@ fail:
* @return the error code (0 if ok).
*/
int g1m_decode_lang_cg(g1m_t *handle, g1m_buffer_t *buffer,
int g1m_decode_std_lang_cg(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
/* set handle type */

295
src/decode/std/mcs.c Normal file
View File

@ -0,0 +1,295 @@
/* *****************************************************************************
* decode/std/mcs.c -- decode an MCS archive file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
#include <stdlib.h>
#define FUNC(NAME) g1m_decode_mcs_##NAME
/* ************************************************************************** */
/* Type correspondance list */
/* ************************************************************************** */
/* MCS file parsing function type */
typedef int (*mcs_decode_func_t)(g1m_mcsfile_t*, g1m_buffer_t*, uint_fast32_t);
/* Correspondance type */
struct mcs_corresp {
unsigned int type;
mcs_decode_func_t decode;
};
/* All correspondances */
static struct mcs_corresp mcs_types[] = {
{g1m_mcstype_program, FUNC(program)},
{g1m_mcstype_list, FUNC(list)},
{g1m_mcstype_mat, FUNC(matrix)},
{g1m_mcstype_vct, FUNC(matrix)},
{g1m_mcstype_spreadsheet, FUNC(spreadsheet)},
{g1m_mcstype_pict, FUNC(picture)},
{g1m_mcstype_capt, FUNC(capture)},
{g1m_mcstype_string, FUNC(string)},
{g1m_mcstype_setup, FUNC(setup)},
{g1m_mcstype_alphamem, FUNC(alphamem)},
{g1m_mcstype_variable, FUNC(alphamem)},
{}
};
/**
* lookup_mcsfile_decode:
* Lookup for a parsing function for an MCS file type.
*
* @arg type the libg1m MCS file type.
* @return the function (NULL if not found).
*/
static mcs_decode_func_t lookup_mcsfile_decode(unsigned int type)
{
/* lookup for the type */
struct mcs_corresp *c = mcs_types;
while (c->decode) {
if (type == c->type)
break;
c++;
}
/* return the function */
return (c->decode);
}
/* ************************************************************************** */
/* Public file functions */
/* ************************************************************************** */
/**
* g1m_decode_mcsfile_head:
* Decode MCS file head.
*
* @arg head the head to fill.
* @arg raw_type the raw file type.
* @arg groupname the groupname (up to 16 bytes).
* @arg dirname the directory name (up to 8 bytes).
* @arg filename the filename (up to 8 bytes).
* @arg filesize the data length.
* @return 0 if the head was filled with success, -1 otherwise.
*/
int g1m_decode_mcsfile_head(g1m_mcshead_t *head,
int raw_type, const unsigned char *groupname,
const unsigned char *dirname, const unsigned char *filename,
uint_fast32_t filesize)
{
/* check that we have a head, lol */
if (!head) return (-1);
/* look for the raw type */
if (g1m_mcstype_get((char*)groupname, (char*)filename, raw_type,
&head->type, &head->id))
head->type = g1m_mcstype_unknown;
log_info("libg1m file type is 0x%04X", head->type);
#if LOGLEVEL <= ll_info
if (g1m_mcstype_uses_id(head->type)) {
log_info("libg1m file id is (%d, %d)", g1m_get_id_major(head->id),
g1m_get_id_minor(head->id));
}
#endif
/* copy the name and size */
memcpy(head->name, filename, 8); head->name[8] = 0;
head->size = filesize;
/* save raw data */
head->_rawtype = raw_type;
memcpy(head->_group, groupname, 16); head->_group[16] = 0;
if (dirname) {
memcpy(head->_dirname, dirname, 8); head->_dirname[8] = 0;
} else memset(head->_dirname, 0, 9);
/* everything went well! */
return (0);
}
/**
* g1m_decode_mcsfile:
* Decode MCS file content.
*
* Part of the public API because of the Protocol 7, where file is sent
* without its header (only with specific subheaders).
*
* @arg handle the handle to make.
* @arg head the head to use.
* @arg buffer the buffer to read from.
* @return the error code (0 if ok).
*/
int g1m_decode_mcsfile(g1m_mcsfile_t **handle, const g1m_mcshead_t *head,
g1m_buffer_t *buffer)
{
int err = 0;
/* check that the head is there */
if (!head) return (g1m_error_op);
/* create handle */
*handle = malloc(sizeof(g1m_mcsfile_t));
if (!handle) return (g1m_error_alloc);
g1m_mcsfile_t *h = *handle;
memset(h, 0, sizeof(g1m_mcsfile_t));
/* copy the head */
memcpy(&h->head, head, sizeof(g1m_mcshead_t));
/* look for the parsing function */
mcs_decode_func_t decode = lookup_mcsfile_decode(head->type);
if (!decode) {
log_error("No dedicated parsing function for this type was found!");
goto notparsing;
}
/* read the buffer (safer) */
uint8_t *buf = malloc(head->size);
if (!buf) return (g1m_error_alloc);
READ(buf, head->size)
/* decode */
g1m_buffer_t membuf = MEMBUFFER(buf, head->size);
err = (*decode)(h, &membuf, head->size);
free(buf);
if (err) goto fail;
/* no error :D */
return (0);
notparsing:
/* allocate enough space */
h->content = malloc(head->size);
err = g1m_error_alloc;
if (!h->content) goto fail;
/* read the content */
GREAD(h->content, head->size)
/* log */
log_info("File content:");
logm_info(h->content, head->size);
/* saved normally */
return (0);
fail:
if (h) {
if (h->content) free(h->content);
free(h);
}
*handle = NULL;
return (err);
}
/**
* g1m_decode_mcsfile_data:
* Decode a MCS file content from raw memory.
*
* @arg handle the file handle.
* @arg head the file head.
* @arg data the buffer data.
* @arg size the buffer size.
* @return the libg1m error.
*/
int g1m_decode_mcsfile_data(g1m_mcsfile_t **handle,
const g1m_mcshead_t *head, const unsigned char *data, size_t size)
{
g1m_buffer_t membuf = MEMBUFFER(data, size);
return (g1m_decode_mcsfile(handle, head, &membuf));
}
/* ************************************************************************** */
/* Main file function */
/* ************************************************************************** */
/**
* g1m_decode_std_mcs:
* Decode an MCS file, after the Standard Header.
*
* @arg handle the handle.
* @arg buffer the buffer to read from.
* @arg num number of sizes.
* @return the error code (0 if ok).
*/
int g1m_decode_std_mcs(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
int err = g1m_error_alloc;
/* get number of subparts from the standard header */
uint_fast16_t num = std->number;
/* allocate memory for the files index */
handle->count = 0;
handle->_size = num;
if (num) {
handle->files = malloc(sizeof(g1m_mcsfile_t*) * num);
if (!handle->files) return (g1m_error_alloc);
}
/* read all of the parts */
log_info("%" PRIuFAST16 " total mcs files to browse", num);
while (handle->count < (int)num) {
/* get the subheader */
GDREAD(hd, mcs_subheader)
/* correct endianess */
hd.subcount = be32toh(hd.subcount);
/* log info about part */
log_info("New group! Group name is '%.16s'.", hd.intname);
log_info("%d mcs files to browse in that group", hd.subcount);
/* foreach subpart */
for (uint_fast32_t i = 0; i < hd.subcount; i++) {
/* get the part header */
GDREAD(fhd, mcs_fileheader)
/* correct endianess */
fhd.datalength = be32toh(fhd.datalength);
/* log info about the subpart */
log_info("[%" PRIuFAST32 "] directory name is '%.8s'",
i, fhd.dirname);
log_info("[%" PRIuFAST32 "] filename is '%.8s'", i, fhd.filename);
log_info("[%" PRIuFAST32 "] data length is %" PRIu32,
i, fhd.datalength);
/* decode the head */
g1m_mcshead_t head;
g1m_decode_mcsfile_head(&head, fhd.filetype, hd.intname,
fhd.dirname, fhd.filename, fhd.datalength);
/* decode */
handle->files[handle->count] = NULL;
err = g1m_decode_mcsfile(&handle->files[handle->count],
&head, buffer);
if (err) goto fail;
handle->count++;
}
}
/* no error */
return (0);
/* was error! */
fail:
g1m_free_mcs(handle);
return (err);
}

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* decode/picture.c -- decode a picture file.
* decode/std/picture.c -- decode a picture file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -36,7 +36,7 @@ static void g3p_deobfuscate(uint8_t *buf, size_t n)
}
/**
* g1m_decode_g3p:
* g1m_decode_std_g3p:
* Decode a G3P file.
*
* @arg handle the handle.
@ -45,7 +45,7 @@ static void g3p_deobfuscate(uint8_t *buf, size_t n)
* @return the error code (0 if ok).
*/
int g1m_decode_g3p(g1m_t *handle, g1m_buffer_t *buffer,
int g1m_decode_std_g3p(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
/* get the G3P global header */
@ -142,7 +142,7 @@ int g1m_decode_g3p(g1m_t *handle, g1m_buffer_t *buffer,
}
/**
* g1m_decode_c2p:
* g1m_decode_std_c2p:
* Decode Classpad images.
*
* @arg handle the handle.
@ -150,7 +150,7 @@ int g1m_decode_g3p(g1m_t *handle, g1m_buffer_t *buffer,
* @return the error code (0 if ok).
*/
int g1m_decode_c2p(g1m_t *handle, g1m_buffer_t *buffer,
int g1m_decode_std_c2p(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
(void)std;

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* decode/storage.c -- decode a storage file.
* decode/std/storage.c -- decode a storage file.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -35,7 +35,7 @@
* @return the error code (0 if ok).
*/
int g1m_decode_storage(g1m_t *handle, g1m_buffer_t *buffer,
int g1m_decode_std_storage(g1m_t *handle, g1m_buffer_t *buffer,
struct standard_header *std)
{
(void)std; int err, ret = 0;

View File

@ -1,6 +1,5 @@
/* *****************************************************************************
* utils/castypes.c -- get the CAS type and data types out of raw
* identification data.
* type/cas.c -- get the CAS type and data types out of raw identification data.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
@ -40,6 +39,8 @@ struct type_corresp {
#define TTERM {NULL, 0}
static struct type_corresp cas_groups[] = {
{"PG", g1m_mcstype_program},
/* not implemented yet types, described by Tom Wheeley and Tom Lynn */
{"AA", 0}, // dynamic graph functions
{"AD", 0}, // variable memory
@ -78,8 +79,7 @@ static struct type_corresp cas_groups[] = {
{"VM", 0}, // Variable (A-Z, etc)
{"WD", 0}, // window data
/* implemented types */
{"PG", g1m_mcstype_program},
/* terminating entry */
TTERM
};

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* utils/type.c -- extract the G1M file type out of raw identification data.
* type/main.c -- extract the G1M file type out of raw identification data.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.

View File

@ -1,5 +1,5 @@
/* *****************************************************************************
* utils/mcstype.c -- get the MCS type out of raw identification data.
* type/mcs.c -- get the MCS type out of raw identification data.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.

58
src/utils/limbuffer.c Normal file
View File

@ -0,0 +1,58 @@
/* *****************************************************************************
* utils/limbuffer.c -- limited libg1m buffer utilities.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libg1m.
* libg1m is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libg1m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libg1m; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libg1m/internals.h>
/**
* g1m_limbuffer_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_limbuffer_read(void *vcookie, unsigned char *buf, size_t size)
{
/* check if the size is okay */
g1m_limited_t *lim = (void*)vcookie;
if (size > lim->left) return (g1m_error_eof);
g1m_buffer_t *buffer = lim->buffer;
/* read */
READ(buf, size)
/* no error */
return (0);
}
/**
* g1m_empty_limbuffer:
* Empty the limit buffer.
*
* @arg limbuf the limbuffer.
*/
int g1m_empty_limbuffer(g1m_buffer_t *limbuffer)
{
g1m_limited_t *lim = (void*)limbuffer->cookie;
g1m_buffer_t *buffer = lim->buffer;
SKIP(lim->left)
return (0);
}

View File

@ -31,8 +31,11 @@
int g1m_membuffer_read(void *vcookie, unsigned char *dest, size_t size)
{
const unsigned char **p = (void*)vcookie;
memcpy(dest, *p, size);
*p += size;
g1m_cursor_t *cursor = (void*)vcookie;
if (size > cursor->left)
return (g1m_error_eof);
memcpy(dest, cursor->p, size);
cursor->p += size;
return (0);
}

View File

@ -38,7 +38,8 @@ int g1m_skip(g1m_buffer_t *buffer, size_t size, uint_fast32_t *checksum)
size_t curlen = min(size, 1024);
size -= curlen;
if ((err = (*buffer->read)(buffer->cookie, buf, curlen))) {
log_error("Skipping has failed after %zu bytes", size);
log_error("Skipping has failed after %" PRIuSIZE " bytes",
orig - size);
return (err);
}