197 lines
5.9 KiB
C
197 lines
5.9 KiB
C
/* *****************************************************************************
|
|
* decode/std/fkey.c -- decode a function keys file.
|
|
* 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>
|
|
|
|
/* ************************************************************************** */
|
|
/* Utilities */
|
|
/* ************************************************************************** */
|
|
/**
|
|
* fkeydup:
|
|
* "Duplicate" function key.
|
|
*
|
|
* @arg fkey fkey to duplicate.
|
|
* @return the "duplicated" function key.
|
|
*/
|
|
|
|
static uint32_t **fkeydup(uint8_t *fkey)
|
|
{
|
|
uint32_t **pixels = alloc_pixels(FKEY_WIDTH, FKEY_HEIGHT);
|
|
if (!pixels) return (NULL);
|
|
prepare_pixels(pixels, FKEY_WIDTH, FKEY_HEIGHT)
|
|
|
|
g1m_decode_picture(pixels, g1m_pictureformat_1bit_packed,
|
|
fkey, FKEY_WIDTH, FKEY_HEIGHT);
|
|
return (pixels);
|
|
}
|
|
|
|
/**
|
|
* fkeydup3:
|
|
* "Duplicate" function key for fx-CG.
|
|
*
|
|
* @arg fkey fkey to duplicate.
|
|
* @return the "duplicated" function key.
|
|
*/
|
|
|
|
static uint32_t **fkeydup3(uint8_t *fkey)
|
|
{
|
|
uint32_t **pixels = alloc_pixels(FKEY3_WIDTH, FKEY3_HEIGHT);
|
|
if (!pixels) return (NULL);
|
|
prepare_pixels(pixels, FKEY3_WIDTH, FKEY3_HEIGHT)
|
|
|
|
g1m_decode_picture(pixels, g1m_pictureformat_1bit_packed,
|
|
fkey, FKEY3_WIDTH, FKEY3_HEIGHT);
|
|
return (pixels);
|
|
}
|
|
|
|
/* ************************************************************************** */
|
|
/* Decoding fx function keys file (G1N) */
|
|
/* ************************************************************************** */
|
|
/**
|
|
* g1m_decode_std_fkey:
|
|
* Decode fx function keys files.
|
|
*
|
|
* @arg h the libg1m handle to create.
|
|
* @arg buffer the buffer to read from.
|
|
* @arg std pointer to the standard header.
|
|
* @return the error code (0 if ok).
|
|
*/
|
|
|
|
int g1m_decode_std_fkey(g1m_handle_t **h, g1m_buffer_t *buffer,
|
|
struct standard_header *std)
|
|
{
|
|
int err; (void)std;
|
|
/* read the subheader */
|
|
DREAD(hd, g1n_subheader)
|
|
uint_fast16_t num = be16toh(hd.fkey_count) + 1;
|
|
|
|
/* beat the best! read the rest! */
|
|
size_t data_size = std->filesize - sizeof(struct standard_header)
|
|
- sizeof(struct g1n_subheader);
|
|
uint8_t data[data_size];
|
|
READ(data, data_size)
|
|
|
|
/* prepare the handle */
|
|
err = g1m_make_fkey(h, g1m_platform_fx, num);
|
|
if (err) return (err);
|
|
g1m_handle_t *handle = *h;
|
|
|
|
/* get the offset table */
|
|
uint16_t *offsets = (uint16_t*)data;
|
|
uint8_t *fkeys = (uint8_t*)(offsets + num);
|
|
|
|
/* read the function keys name */
|
|
handle->g1m_handle_title[16] = 0;
|
|
strncpy(handle->g1m_handle_title, (char*)fkeys, 16);
|
|
|
|
/* read all */
|
|
for (handle->g1m_handle_count = 0; handle->g1m_handle_count < (int)num;
|
|
handle->g1m_handle_count++) {
|
|
int i = handle->g1m_handle_count;
|
|
if (offsets[i] == (uint16_t)-1)
|
|
continue ;
|
|
offsets[i] = be16toh(offsets[i]);
|
|
|
|
/* store */
|
|
handle->g1m_handle_fkeys[i] = fkeydup(&fkeys[i]);
|
|
if (!handle->g1m_handle_fkeys[i]) goto fail;
|
|
}
|
|
|
|
/* no error */
|
|
return (0);
|
|
|
|
/* omg fail! */
|
|
fail:
|
|
g1m_free(*h); *h = NULL;
|
|
return (err);
|
|
}
|
|
|
|
/* ************************************************************************** */
|
|
/* Decoding fx-CG/Prizm function keys file (G3N) */
|
|
/* ************************************************************************** */
|
|
/**
|
|
* g1m_decode_std_cg_fkey:
|
|
* Decode fx-CG key files.
|
|
*
|
|
* @arg handle the libg1m handle.
|
|
* @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_fkey(g1m_handle_t **h, g1m_buffer_t *buffer,
|
|
struct standard_header *std, struct standard_subheader *sub,
|
|
struct _prizm_subheader *prizm, uint32_t *check)
|
|
{
|
|
int err = g1m_error_alloc; uint8_t *data = NULL;
|
|
(void)std; (void)prizm;
|
|
|
|
/* read the subheader */
|
|
DREAD(lhd, g3l_lang_header)
|
|
*check = g1m_checksum32(&lhd, sizeof(struct g3l_lang_header), *check);
|
|
|
|
/* read the data */
|
|
size_t data_size = be32toh(sub->filesize) - sizeof(struct standard_header)
|
|
- sizeof(struct standard_subheader) - sizeof(struct _prizm_subheader)
|
|
- sizeof(struct g3l_lang_header) - 4;
|
|
if (!(data = malloc(data_size))) goto fail;
|
|
READ(data, data_size)
|
|
*check = g1m_checksum32(data, data_size, *check);
|
|
|
|
/* make the handle */
|
|
int num = be32toh(lhd.num);
|
|
err = g1m_make_fkey(h, g1m_platform_cg, num);
|
|
if (err) return (err);
|
|
g1m_handle_t *handle = *h;
|
|
|
|
/* setup the pointers */
|
|
uint32_t *offsets = (void*)data;
|
|
uint8_t *messages = (uint8_t*)&offsets[num + 1];
|
|
|
|
/* read messages */
|
|
for (handle->g1m_handle_count = 0; handle->g1m_handle_count < (int)num;
|
|
handle->g1m_handle_count++) {
|
|
int i = handle->g1m_handle_count;
|
|
if (offsets[i] == (uint32_t)-1) {
|
|
log_info("[#%d] -", i);
|
|
continue;
|
|
}
|
|
|
|
/* correct offset and log */
|
|
offsets[i] = be32toh(offsets[i]);
|
|
log_info("[#%d] '%s' (0x%" PRIu32 ")", i,
|
|
&messages[offsets[i]], offsets[i]);
|
|
|
|
/* store */
|
|
handle->g1m_handle_fkeys[i] = fkeydup3((void*)&messages[offsets[i]]);
|
|
if (!handle->g1m_handle_fkeys[i]) goto fail;
|
|
}
|
|
|
|
/* done */
|
|
free(data);
|
|
return (0);
|
|
|
|
fail:
|
|
free(data);
|
|
g1m_free(*h); *h = NULL;
|
|
return (err);
|
|
}
|