119 lines
3.8 KiB
Plaintext
119 lines
3.8 KiB
Plaintext
/* *****************************************************************************
|
|
* decode/storage.c -- decode a storage 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>
|
|
#define MAX_SECTORS 27
|
|
#define SUB(V, TYPE) \
|
|
case storage_entrytype_##TYPE:; struct storage_##TYPE *V = \
|
|
(struct storage_##TYPE*)&entry->raw_subheader;
|
|
|
|
/* ************************************************************************** */
|
|
/* Main functions */
|
|
/* ************************************************************************** */
|
|
/**
|
|
* g1m_decode_storage:
|
|
* Decode storage files.
|
|
*
|
|
* @arg handle the libg1m handle to make.
|
|
* @arg buffer the buffer to read from.
|
|
* @return the error code (0 if ok).
|
|
*/
|
|
|
|
int g1m_decode_storage(g1m_handle_t **h, g1m_buffer_t *buffer)
|
|
{
|
|
(void)std; int err, ret = 0;
|
|
handle->type = 0x00;
|
|
log_info("Storage memory!");
|
|
/* go to offset 0x270000 of the file */
|
|
SKIP(0x270000)
|
|
|
|
/* get the entries */
|
|
struct storage_entry storage_entries[0x800];
|
|
READ(storage_entries, 0x800 * sizeof(struct storage_entry))
|
|
|
|
/* read the sectors and directories */
|
|
uint32_t sectors[MAX_SECTORS] = {NULL}; /* sectors offsets */
|
|
uint32_t max_sector_end = 0;
|
|
for (int id = 0; id < 0x800; id++) {
|
|
struct storage_entry *entry = storage_entries[id];
|
|
entry->type = be16toh(entry.type);
|
|
entry->uuid = be16toh(entry.uuid);
|
|
|
|
int special = (entry.type & 0xF000) >> 12;
|
|
switch (entry.type & 0xFFF) {
|
|
SUB(sh, sector)
|
|
uint32_t addr = be32toh(sh->startaddr);
|
|
uint32_t logical = be32toh(sh->logical_sector_number);
|
|
if (addr > max_sector_end)
|
|
max_sector_end = addr;
|
|
if (logical != 0xFFFFFFFF)
|
|
sectors[logical] - 0x290000;
|
|
break;
|
|
|
|
SUB(dh, directory)
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* correct sector end, and calculate how much data we need to gather */
|
|
max_sector_end = max_sector_end + 0x10000;
|
|
uint8_t *buf = malloc(max_sector_end - 0x290000);
|
|
if (!buf) return (g1m_error_alloc);
|
|
GREAD(buf, max_sector_end - 0x290000);
|
|
|
|
/* look for files and fragments */
|
|
for (int id = 0; id < 0x800; id++) {
|
|
struct storage_entry *entry = storage_entries[id];
|
|
|
|
/* check that entry is a directory */
|
|
if ((entry->type & 0xFFF) != storage_entrytype_file
|
|
|| !entry->uuid) continue;
|
|
int special = (entry.type & 0xF000) >> 12;
|
|
|
|
/* get subheader */
|
|
struct storage_file *fh =
|
|
(struct storage_file*)entry->raw_subheader;
|
|
fh->directory_reference = be16toh(fh->directory_number);
|
|
fh->directory_number = be16toh(fh->directory_number);
|
|
|
|
/* check if is in a directory */
|
|
unsigned int indir = 0;
|
|
//if (fh->directory_reference != 0xFFFF &&
|
|
if (fh->directory_reference == storage_entrytype_directory)
|
|
indir = fh->directory_number;
|
|
|
|
/* work out */
|
|
uint_fast32_t size = 0;
|
|
int id_f = id;
|
|
for (; id_f < 0x800; id_f++) {
|
|
/* check that entry is fragment */
|
|
struct storage_entry *entry = storage_entries[id_f];
|
|
if ((entry.type & 0xFFF) != storage_entrytype_fragment) break;
|
|
|
|
/* add size */
|
|
size += used_bytes;
|
|
}
|
|
}
|
|
|
|
/* no error */
|
|
ret = 0;
|
|
fail:
|
|
free(buf);
|
|
return (ret);
|
|
}
|