/* ***************************************************************************** * decode/std/addin.c -- decode an add-in 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 /* ************************************************************************** */ /* Add-in for the fx-9860G (G1A) */ /* ************************************************************************** */ /** * g1m_decode_std_addin: * Decodes a "normal" add-in (after Standard Header). * * @arg h the handle to make. * @arg buffer the buffer to read from. * @return the error code (0 if ok). */ int g1m_decode_std_addin(g1m_t **h, g1m_buffer_t *buffer, struct standard_header *std) { int err = 0; (void)std; /* get the subheader */ DREAD(hd, g1a_subheader) hd.filesize = be32toh(hd.filesize); /* make the handle */ g1m_version_t version; g1m_decode_version((char*)hd.version, &version); time_t created; g1m_decode_date((char*)hd.creation_date, &created); size_t content_size = hd.filesize; /* already corrected */ content_size -= sizeof(struct standard_header) + sizeof(struct g1a_subheader); err = g1m_make_addin(h, g1m_platform_fx, content_size, &version, &created); if (err) return (err); g1m_t *handle = *h; /* set more data */ strncpy(handle->title, (char*)hd.title, 8); handle->title[8] = 0; strncpy(handle->intname, (char*)hd.internal_name, 8); handle->intname[8] = 0; /* log info about the subheader */ log_info("title is '%s'", handle->title); log_info("internal name is '%s'", handle->intname); log_info("estrips count is %" PRIu8, hd.estrips_count); log_info("version is %02u.%02u.%04u", handle->version.major, handle->version.minor, handle->version.revision); log_info("creation date is: %.24s", ctime(&handle->creation_date)); /* fill icon */ g1m_decode_picture(handle->icon_unsel, g1m_pictureformat_1bit, hd.icon, handle->width, handle->height); g1m_decode_picture(handle->icon_sel, g1m_pictureformat_1bit_r, hd.icon, handle->width, handle->height); /* read content */ GREAD(handle->content, handle->size) /* no errors */ return (err); fail: g1m_free(*h); *h = NULL; return (err); } /* ************************************************************************** */ /* Add-in for the fx-CP/Classpad (C1A) */ /* ************************************************************************** */ /** * g1m_decode_std_cp_addin: * Decode fx-CP add-in. * * @arg h the handle to make. * @arg buffer the buffer to read from. * @arg std the standard header. * @arg sub the standard subheader. * @arg cp the classpad-specific subheader. * @arg check the checksum to feed. * @return the error code (0 if ok). */ int g1m_decode_std_cp_addin(g1m_t **h, g1m_buffer_t *buffer, struct standard_header *std, struct standard_subheader *sub, struct _classpad_subheader *cp, uint32_t *check) { int err = 0; (void)std; (void)cp; /* read the add-in subheader */ DREAD(cphd, c1a_subheader) *check = g1m_checksum32(&cphd, sizeof(struct c1a_subheader), *check); /* make the handle */ g1m_version_t version; g1m_decode_version((char*)sub->version, &version); time_t created; g1m_decode_date((char*)sub->timestamp, &created); size_t content_size = be32toh(sub->filesize) - 0x1000; err = g1m_make_addin(h, g1m_platform_cp, content_size, &version, &created); if (err) return (err); g1m_t *handle = *h; /* copy other basic information */ strncpy(handle->intname, (char*)sub->internal_name, 8); handle->intname[9] = 0; strncpy(handle->title, (char*)sub->title, 16); handle->title[16] = 0; /* decode pictures */ g1m_decode_picture(handle->icon_unsel, g1m_pictureformat_1bit_packed, cphd.icon, handle->width, handle->height); g1m_decode_picture(handle->icon_sel, g1m_pictureformat_1bit_packed_r, cphd.icon, handle->width, handle->height); /* log */ log_info("title is '%s'", handle->title); log_info("internal name is '%s'", handle->intname); log_info("version is %02u.%02u.%04u", handle->version.major, handle->version.minor, handle->version.revision); log_info("timestamp is %.24s", ctime(&handle->creation_date)); /* get content */ GREAD(handle->content, handle->size) *check = g1m_checksum32(handle->content, handle->size, *check); /* no error */ return (0); fail: g1m_free(*h); *h = NULL; return (err); } /* ************************************************************************** */ /* Add-in for the fx-CG/Prizm (G3A) */ /* ************************************************************************** */ /** * g1m_decode_std_cg_addin: * Decode fx-CG add-in. * * @arg h the handle to make. * @arg buffer the buffer to read from. * @arg std the standard header. * @arg sub the standard subheader. * @arg prizm the prizm-specific subheader. * @arg check the checksum to feed. * @return the error code (0 if ok). */ int g1m_decode_std_cg_addin(g1m_t **h, g1m_buffer_t *buffer, struct standard_header *std, struct standard_subheader *sub, struct _prizm_subheader *prizm, uint32_t *check) { int err = 0; (void)std; (void)prizm; /* read the add-in subheader */ DREAD(cghd, g3a_subheader) *check = g1m_checksum32(&cghd, sizeof(struct g3a_subheader), *check); /* make the handle */ g1m_version_t version; g1m_decode_version((char*)sub->version, &version); time_t created; g1m_decode_date((char*)sub->timestamp, &created); size_t content_size = be32toh(sub->filesize); content_size -= sizeof(struct standard_header) + sizeof(struct standard_subheader) + sizeof(struct _prizm_subheader) + sizeof(struct g3a_subheader) + sizeof(uint32_t); log_info("Content size is %" PRIuSIZE, content_size); err = g1m_make_addin(h, g1m_platform_cg, content_size, &version, &created); if (err) return (err); g1m_t *handle = *h; /* copy other basic information */ strncpy(handle->intname, (char*)sub->internal_name, 8); handle->intname[9] = 0; strncpy(handle->title, (char*)sub->title, 16); handle->title[16] = 0; /* decode pictures */ g1m_decode_picture(handle->icon_unsel, g1m_pictureformat_16bit, cghd.unselected_icon_image, handle->width, handle->height); g1m_decode_picture(handle->icon_sel, g1m_pictureformat_16bit, cghd.selected_icon_image, handle->width, handle->height); /* log */ log_info("title is '%s'", handle->title); log_info("internal name is '%s'", handle->intname); log_info("version is %02u.%02u.%04u", handle->version.major, handle->version.minor, handle->version.revision); log_info("timestamp is %.24s", ctime(&handle->creation_date)); /* read content */ GREAD(handle->content, handle->size) *check = g1m_checksum32(handle->content, handle->size, *check); /* no error */ return (0); fail: g1m_free(*h); *h = NULL; return (err); }