cake
/
libg1m
Archived
1
0
Fork 0
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libg1m/src/decode/std/lang.c

162 lines
4.9 KiB
C

/* *****************************************************************************
* decode/std/lang.c -- decode a language 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>
/* ************************************************************************** */
/* fx language files parsing */
/* ************************************************************************** */
/**
* g1m_decode_std_lang:
* Decode fx language files.
*
* @arg h the libg1m handle to create.
* @arg buffer the buffer to read from.
* @return the error code (0 if ok).
*/
int g1m_decode_std_lang(g1m_handle_t **h, g1m_buffer_t *buffer,
struct standard_header *std)
{
(void)std; int err;
/* read the subheader */
DREAD(hd, g1l_subheader)
uint_fast16_t num = be16toh(hd.message_count) + 1;
/* log */
log_info("%" PRIuFAST16 " messages to read", num);
/* beat the best, read the rest! */
size_t data_size = std->filesize - sizeof(struct standard_header)
- sizeof(struct g1l_subheader);
uint8_t data[data_size];
READ(data, data_size)
/* make the handle */
err = g1m_make_lang(h, g1m_platform_fx, num);
if (err) return (err);
g1m_handle_t *handle = *h;
/* get the offset table */
uint16_t *offsets = (uint16_t*)data;
char *messages = (char*)(offsets + num);
/* 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] == (uint16_t)-1) {
log_info("[#%d] -", i);
continue;
}
/* correct offset and log */
offsets[i] = be16toh(offsets[i]);
log_info("[#%d] '%s' (0x%" PRIu16 ")", i,
&messages[offsets[i]], offsets[i]);
/* store */
handle->g1m_handle_messages[i] = strdup(&messages[offsets[i]]);
if (!handle->g1m_handle_messages[i]) goto fail;
handle->g1m_handle_count++;
}
/* no error */
return (0);
/* omg fail! */
fail:
g1m_free(*h); *h = NULL;
return (err);
}
/* ************************************************************************** */
/* Decoding language files for fx-CG/Prizm (G3L) */
/* ************************************************************************** */
/**
* g1m_decode_std_cg_lang:
* Decode fx-CG language file.
*
* @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_lang(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_lang(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_messages[i] = strdup((char*)&messages[offsets[i]]);
if (!handle->g1m_handle_messages[i]) goto fail;
}
/* done */
free(data);
return (0);
fail:
free(data);
g1m_free(*h); *h = NULL;
return (err);
}