cake
/
libg1m
Archived
1
0
Fork 0
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libg1m/src/type/std.c

253 lines
7.1 KiB
C

/* *****************************************************************************
* type/std.c -- extract the STD file type out of raw identification data.
* 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 <ctype.h>
/* ************************************************************************** */
/* Local types */
/* ************************************************************************** */
/* Flags */
#define nochk_controlone 0x01
#define nochk_controltwo 0x02
/* Subtype correspondance type */
struct type_info {
/* identification */
const char *type;
/* info */
const char *info;
unsigned int flags;
/* types */
unsigned int platform;
unsigned int libtype;
};
/* Main type correspondance type */
struct main_info {
/* identification */
const char *type;
/* subtypes */
struct type_info *subtypes;
};
/* ************************************************************************** */
/* Correspondances */
/* ************************************************************************** */
/* Terminate type list */
#define TTERM {NULL, NULL, 0, 0, 0}
/* Common magic types */
#define magic_common "\x00\x10\x00\x10\x00"
#define cp_magic "\x00\x01\x00\x01\x00"
#define blank "\xFF\xFF\xFF\xFF\xFF\xFF"
/* Main types */
static struct main_info types[] = {
/* USBPower (the most common one) */
{"USBPower", (struct type_info[]){
/* add-ins */
{"\xf3" magic_common, "add-in", 0,
g1m_platform_fx, g1m_type_addin},
{"\x2c" cp_magic, "fx-CG add-in", 0,
g1m_platform_cg, g1m_type_addin},
/* MCS */
{"\x62" magic_common, "mcs (g2r)", 0,
g1m_platform_fx, g1m_type_mcs}, /* TODO: add flag? */
{"\x31" magic_common, "mcs", 0,
g1m_platform_fx, g1m_type_mcs},
{"\x75" magic_common, "mcs (fx-CG)", 0,
g1m_platform_cg, g1m_type_mcs},
/* Language */
{"\x12" magic_common, "fx language file", 0,
g1m_platform_fx, g1m_type_lang},
/* E-Activities */
{"\x49" magic_common, "e-activity (document)", 0,
g1m_platform_fx, g1m_type_eact},
/* Pictures */
{"\x7d" magic_common, "fx-CG picture", 0,
g1m_platform_cg, g1m_type_pict},
TTERM
}},
/* Ly755 (Classpad-specific) */
{"Ly755 ", (struct type_info[]){
{"\x2c" cp_magic, "fx-CG language file", 0,
g1m_platform_cg, g1m_type_lang},
TTERM
}},
/* CASIO (only used for c2p...?) */
{"CASIO\0\0\0", (struct type_info[]){
{"c2p\0\0\0", "Classpad picture", nochk_controlone | nochk_controltwo,
g1m_platform_cp, g1m_type_pict},
TTERM
}},
/* terminating */
{NULL, NULL}
};
/* ************************************************************************** */
/* Extensions comparison */
/* ************************************************************************** */
/* Extension correspondance type */
struct ext_corresp {
/* identification */
const char *ext;
/* data */
const char *info;
unsigned int platform;
unsigned int libtype;
};
/* Extension correspondances */
static struct ext_corresp ext_types[] = {
/* storage files */
{"g1s", "Storage file", g1m_platform_none, g1m_type_storage},
/* fx types with non-checked header */
{"g1l", "fx language file", g1m_platform_fx, g1m_type_lang},
{"g1n", "fx fkeys file", g1m_platform_fx, g1m_type_fkey},
/* cg types with non-checked header */
{"g3l", "fx-CG language file", g1m_platform_cg, g1m_type_lang},
{"g3n", "fx-CG fkeys file", g1m_platform_cg, g1m_type_fkey},
/* sentinel */
{NULL, NULL, 0, 0}
};
/**
* get_extension:
* Get extension from a path.
*
* @arg path the path.
* @arg extbuf the extension buffer.
* @return extension.
*/
static void get_extension(const char *path, char *extbuf)
{
/* get filename */
const char *filename = strrchr(path, '/');
filename = filename ? filename + 1 : path;
/* get extension */
const char *ext = strrchr(filename, '.');
ext = ext ? ext + 1 : filename;
/* copy it */
extbuf[4] = 0; strncpy(extbuf, ext, 4);
for (int i = 0; i < 3; i++)
extbuf[i] = tolower(extbuf[i]);
}
/* ************************************************************************** */
/* Main functions */
/* ************************************************************************** */
/**
* g1m_maketype_std:
* Get type info.
*
* @arg path Path of the file.
* @arg main_id The main ID (at least 8 bytes).
* @arg subtype The subtype (at least 6 bytes).
* @arg info Pointer to the info string to set.
* @arg check_one Check first control byte.
* @arg check_two Check second control byte.
* @arg platform Pointer to the platform to set.
* @arg type Pointer to the type to set.
* @return If there was an error.
*/
int g1m_maketype_std(const char *path,
unsigned char *main_id, unsigned char *subtype,
const char **info, int *check_one, int *check_two,
unsigned int *platform, g1m_type_t *type)
{
/* look if blank */
if (!memcmp(main_id, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8)
&& !memcmp(subtype, "\xFF\xFF\xFF\xFF\xFF\xFF", 6)) {
log_info("Blank type! Let's use the extension to try and identify it.");
if (!path) return (1);
char ext[5]; get_extension(path, ext);
struct ext_corresp *e = ext_types - 1;
while ((++e)->ext) {
if (!strcmp(e->ext, ext))
break ;
}
if (!e->ext) {
log_fatal("No matching extension with '%s'!", ext);
return (1);
}
/* fill in info */
if (info) *info = e->info;
if (platform) *platform = e->platform;
if (type) *type = e->libtype;
if (check_one) *check_one = 0;
if (check_two) *check_two = 0;
} else {
/* look for main_id */
struct main_info *mt = types - 1;
while ((++mt)->type) {
if (!memcmp(mt->type, main_id, 8))
break ;
}
if (!mt->type) {
log_fatal("Main ID not recognized:");
logm_info(main_id, 8);
return (1);
}
/* look for subtype */
struct type_info *sub = mt->subtypes;
while (sub->type) {
if (!memcmp(sub->type, subtype, 6))
break ;
sub++;
}
if (!sub->type) {
log_fatal("Type not managed (yet?):");
logm_info(subtype, 6);
return (1);
}
/* fill in info */
if (info) *info = sub->info;
if (platform) *platform = sub->platform;
if (type) *type = sub->libtype;
if (check_one) *check_one = ~sub->flags & nochk_controlone;
if (check_two) *check_two = ~sub->flags & nochk_controltwo;
}
return (0);
}