/* ***************************************************************************** * decode/std.c -- decode a "standard" CASIO file. * 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 #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 */ decode_func decode; }; /* The correspondances */ static struct corresp parsing_functions[] = { /* add-ins */ {g1m_platform_fx, g1m_type_addin, FUNC(addin)}, {g1m_platform_cg, g1m_type_addin, FUNC(addin_cg)}, /* mcs */ {g1m_platform_fx, g1m_type_mcs, FUNC(mcs)}, {g1m_platform_cg, g1m_type_mcs, FUNC(mcs)}, /* language files */ {g1m_platform_fx, g1m_type_lang, FUNC(lang)}, {g1m_platform_cg, g1m_type_lang, FUNC(lang_cg)}, /* function keys file */ {g1m_platform_fx, g1m_type_fkey, FUNC(fkey)}, {g1m_platform_cg, g1m_type_fkey, FUNC(lang_cg)}, /* e-activities */ {g1m_platform_fx, g1m_type_eact, FUNC(eact)}, /* pictures */ {g1m_platform_cg, g1m_type_pict, FUNC(g3p)}, {g1m_platform_cp, g1m_type_pict, FUNC(c2p)}, /* storage */ /*{g1m_platform_none, g1m_type_storage, g1m_decode_storage},*/ {0, 0, NULL} }; /** * 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 decode function. * @return the error code (0 if ok). */ static int find_decode_function(g1m_t *handle, const char *path, struct standard_header *std, decode_func *rd) { /* get the type */ unsigned int platform, type; const char *type_string; int check_one, check_two; if (g1m_get_type_info(path, std->main_id, std->subtype, &type_string, &check_one, &check_two, &platform, &type)) return (g1m_error_magic); log_info("Standard Header type is '%s'.", type_string); /* check control bytes */ if (check_one && std->control != ((std->filesize + 0x41) & 0xff)) { log_info("First control byte isn't right."); return (g1m_error_magic); } else if (check_two && std->control2 != ((std->filesize + 0xb8) & 0xff)) { log_info("Second control byte isn't right."); return (g1m_error_magic); } /* look for corresponding parsing function */ struct corresp *c = parsing_functions - 1; while ((++c)->decode) { if (c->type != type) continue; if (c->platform != platform) continue; break; } if (!c->decode) { log_fatal("No parsing function was found for this type."); return (g1m_error_magic); } /* set the vars */ handle->type = type; handle->platform = platform; *rd = c->decode; return (0); } /* ************************************************************************** */ /* Main standard header decoding function */ /* ************************************************************************** */ /** * g1m_decode_std: * Decode a file with standard header. * * @arg handle the handle. * @arg path the path. * @arg buffer the buffer to read from. * @arg std the standard header. * @arg expected_types the expected types. * @return the error code (0 if ok). */ 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 */ uint8_t *u = (uint8_t*)std; for (size_t i = 0; i < sizeof(struct standard_header); i++) u[i] = ~u[i]; /* print header */ log_info("Raw inverted standard header is:"); logm_info(std, sizeof(struct standard_header)); /* correct standard header endianess */ std->filesize = be32toh(std->filesize); std->number = be16toh(std->number); /* get type */ decode_func read_func; int err; if ((err = find_decode_function(handle, path, std, &read_func))) return (err); /* check if the type is alright */ if (expected_types && handle->type != expected_types) return (g1m_error_wrong_type); /* log some data */ log_info("Standard Header filesize is %" PRIu32 "o.", std->filesize); log_info("Standard Header num is %" PRIu16 ".", std->number); /* subdecode. */ return ((*read_func)(handle, buffer, std)); }