125 lines
3.7 KiB
C
125 lines
3.7 KiB
C
/* ************************************************************************** */
|
|
/* _____ _ */
|
|
/* parse/main.c |_ _|__ _ _| |__ ___ _ _ */
|
|
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
|
/* | | (_) | |_| | | | | __/ |_| | */
|
|
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
|
/* Last updated: 2016/11/02 14:47:49 |___/ */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
#include <libg1m/internals.h>
|
|
|
|
/**
|
|
* get_main_id:
|
|
* Get numerical main ID based on the main ID string.
|
|
*
|
|
* @arg s the 8-bytes buffer containing the ID.
|
|
* @return the main ID or -1 if the main ID is unknown.
|
|
*/
|
|
|
|
static int get_main_id(unsigned char *s)
|
|
{
|
|
if (!memcmp(s, "USBPower", 8))
|
|
return (g1m_mid_usbpower);
|
|
if (!memcmp(s, "Ly755 ", 8))
|
|
return (g1m_mid_ly755);
|
|
return (-1);
|
|
}
|
|
|
|
/**
|
|
* g1m_parse:
|
|
* Parse a G1M file.
|
|
*
|
|
* Read the standard header, correct endianness, check magic numbers,
|
|
* then read subparts according to the G1M type.
|
|
*
|
|
* @arg handle the handle.
|
|
* @arg stream the stream to parse from.
|
|
* @return the error code (0 if ok).
|
|
*/
|
|
|
|
int g1m_parse(g1m_t *handle, FILE *stream)
|
|
{
|
|
/* initialize the handle */
|
|
bzero(handle, sizeof(g1m_t));
|
|
|
|
/* get the standard header */
|
|
DREAD(hd, standard_header)
|
|
|
|
/* reverse */
|
|
uint8_t *u = (uint8_t*)&hd;
|
|
for (size_t i = 0; i < sizeof(struct standard_header); i++) u[i] = ~u[i];
|
|
|
|
/* print header */
|
|
log_info("Raw standard header is:");
|
|
logm_info(&hd, sizeof(struct standard_header));
|
|
|
|
/* correct standard header endianess */
|
|
hd.filesize = be32toh(hd.filesize);
|
|
hd.number = be16toh(hd.number);
|
|
|
|
/* check standard header magics */
|
|
if (hd.control != ((hd.filesize + 0x41) & 0xff)) {
|
|
log_info("First control byte isn't right.");
|
|
return (g1m_error_magic);
|
|
} else if (hd.control2 != ((hd.filesize + 0xb8) & 0xff)) {
|
|
log_info("Second control byte isn't right.");
|
|
return (g1m_error_magic);
|
|
}
|
|
|
|
/* get the main ID */
|
|
int main_id = get_main_id(hd.main_id);
|
|
if (main_id < 0) {
|
|
log_fatal("Main ID is unknown: '%.8s'", hd.main_id);
|
|
return (g1m_error_magic);
|
|
}
|
|
|
|
/* log some data */
|
|
log_info("Standard Header Main ID is '%.8s'", hd.main_id);
|
|
log_info("Standard Header Type is '%s' (0x%02x)",
|
|
g1m_get_type_string(main_id, hd.type), hd.type);
|
|
log_info("Standard Header filesize is %uo", hd.filesize);
|
|
log_info("Standard Header num is %d.", hd.number);
|
|
|
|
/* subparse. */
|
|
handle->is_cg = 0;
|
|
switch (main_id) {
|
|
case g1m_mid_usbpower:
|
|
switch (hd.type) {
|
|
case g1m_usbpower_type_addin:
|
|
handle->type = g1m_type_addin;
|
|
return (g1m_parse_addin(handle, stream));
|
|
case g1m_usbpower_type_addin_cg:
|
|
handle->type = g1m_type_addin;
|
|
handle->is_cg = 1;
|
|
return (g1m_parse_addin_cg(handle, stream, &hd));
|
|
case g1m_usbpower_type_g2r:
|
|
case g1m_usbpower_type_mcs:
|
|
handle->type = g1m_type_mcs;
|
|
return (g1m_parse_mcs(handle, stream, hd.number));
|
|
case g1m_usbpower_type_eact:
|
|
handle->type = g1m_type_eact;
|
|
return (g1m_parse_eact(handle, stream));
|
|
case g1m_usbpower_type_g3p:
|
|
handle->type = g1m_type_pict;
|
|
handle->is_cg = 1;
|
|
return (g1m_parse_g3p(handle, stream, &hd));
|
|
default:
|
|
log_info("Type not managed (yet?): 0x%02x", hd.type);
|
|
}
|
|
break;
|
|
case g1m_mid_ly755:
|
|
switch (hd.type) {
|
|
case g1m_ly755_type_lang:
|
|
log_info("Lang type isn't managed yet.");
|
|
break;
|
|
default:
|
|
log_info("Type not managed (yet?): 0x%02x", hd.type);
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* no error */
|
|
return (0);
|
|
}
|