/* ***************************************************************************** * type/std.c -- extract the STD file type out of raw identification data. * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey * * 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 . * ************************************************************************** */ #include #include #define f_c1 g1m_stdflag_check1 #define f_c2 g1m_stdflag_check2 #define f_sub g1m_stdflag_sub #define f_pic g1m_stdflag_pic /* ************************************************************************** */ /* Local types */ /* ************************************************************************** */ /* 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", f_c1 | f_c2, g1m_platform_fx, g1m_type_addin}, {"\x2c" cp_magic, "fx-CG add-in", f_c1 | f_c2 | f_sub, g1m_platform_cg, g1m_type_addin}, /* MCS */ {"\x62" magic_common, "mcs (g2r)", f_c1 | f_c2, g1m_platform_fx, g1m_type_mcs}, /* TODO: add flag? */ {"\x31" magic_common, "mcs", f_c1 | f_c2, g1m_platform_fx, g1m_type_mcs}, {"\x75" magic_common, "mcs (fx-CG)", f_c1 | f_c2, g1m_platform_cg, g1m_type_mcs}, /* Language */ {"\x12" magic_common, "fx language file", f_c1 | f_c2, g1m_platform_fx, g1m_type_lang}, /* E-Activities */ {"\x49" magic_common, "e-activity (document)", f_c1 | f_c2, g1m_platform_fx, g1m_type_eact}, /* Pictures */ {"\x7d" magic_common, "fx-CG picture", f_c1 | f_c2 | f_pic, g1m_platform_cg, g1m_type_pict}, TTERM }}, /* Ly755 (Classpad-specific) */ {"Ly755 ", (struct type_info[]){ {"\x2c" cp_magic, "fx-CG language file", f_c1 | f_c2 | f_sub, 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", f_pic, 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; unsigned int flags; }; /* Extension correspondances */ static struct ext_corresp ext_types[] = { /* fx types */ {"g1l", "fx language file", g1m_platform_fx, g1m_type_lang, 0}, {"g1n", "fx fkeys file", g1m_platform_fx, g1m_type_fkey, 0}, {"g1m", "fx mcs archive", g1m_platform_fx, g1m_type_mcs, 0}, {"g1r", "fx mcs backup", g1m_platform_fx, g1m_type_mcs, 0}, {"g2m", "fx OS2 mcs archive", g1m_platform_fx, g1m_type_mcs, 0}, {"g2r", "fx OS2 mcs backup", g1m_platform_fx, g1m_type_mcs, 0}, {"g1a", "fx add-in", g1m_platform_fx, g1m_type_addin, 0}, {"g1e", "fx e-activity", g1m_platform_fx, g1m_type_eact, 0}, /* fx-CP types */ {"c1a", "classpad add-in", g1m_platform_cp, g1m_type_addin, f_sub}, {"c2p", "classpad picture", g1m_platform_cp, g1m_type_pict, f_pic}, /* fx-CG types */ {"g3l", "fx-CG language file", g1m_platform_cg, g1m_type_lang, f_sub}, {"g3n", "fx-CG fkeys file", g1m_platform_cg, g1m_type_fkey, f_sub}, {"g3a", "fx-CG add-in", g1m_platform_cg, g1m_type_addin, f_sub}, {"g3e", "fx-CG e-activity", g1m_platform_cg, g1m_type_eact, 0}, {"g3p", "fx-CG picture", g1m_platform_cg, g1m_type_pict, f_pic}, /* sentinel */ {NULL, NULL, 0, 0, 0} }; /* ************************************************************************** */ /* 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, unsigned int *flags, 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]; g1m_getext(path, ext, 5); 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 (flags) *flags = e->flags; } 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 (flags) *flags = sub->flags; } return (0); }