cake
/
libg1m
Archived
1
0
Fork 0

Added basic parsing of storage files

This commit is contained in:
Thomas Touhey 2016-12-29 02:07:32 +01:00
parent a11dc9e42b
commit ddd98ff9c4
3 changed files with 216 additions and 10 deletions

View File

@ -10,14 +10,140 @@
#ifndef LIBG1M_FORMAT_STORAGE_H
# define LIBG1M_FORMAT_STORAGE_H
/* Storage files (G1S) contain backups of the storage memory.
/* Storage backup files (G1S) contain backups of the storage memory.
* It corresponds exactly to the on-calc storage memory structure.
*
* According to Simon Lothar, the files contain zeroes up to 0x00270000
* (the location of the MCS in real fx-9860 calculators), then it has the
* same structure than on the calculator. These files exist because FA-124
* implements Bfile as well as the calculator (brilliant, huh?).
* (including the StandardHeader; this is the location of the SMEM in real
* fx-9860 calculators), then it has the same structure than the one
* used by the calculator.
*
* The structure has been documented by Simon Lothar, but I haven't
* worked on it yet: TODO. */
* It looks like these files are not managed by the calculator (not directly);
* however, they are managed by FA-124. */
/* ************************************************************************** */
/* Directory list */
/* ************************************************************************** */
/* The SMEM (content of the G1S file once 0x270000 bytes were skipped) starts
* with a big entry list. An entry is 32-bytes long: it starts with a common
* part, then with a type-specific part (then unused bytes if the subheader
* is less than 28-bytes long). Here is its structure: */
struct storage_entry {
/* the type number - see below */
uint16_t type;
/* the unique number of the entry */
uint16_t uuid;
/* the raw subheader */
uint8_t raw_subheader[28];
};
/* The `type` is composed of three nibbles of identification (`type & 0xFFF`)
* and a (high) nibble of special properties, keep that in mind.
* Here are the known types: */
enum storage_entry_type {
storage_entrytype_sector = 0x200,
storage_entrytype_directory = 0x110,
storage_entrytype_file = 0x120,
storage_entrytype_fragment = 0x130,
};
/* There is no count of the entries, but there is a terminating entry,
* identified by its type being 0xFFFF. */
/* ************************************************************************** */
/* Sectors */
/* ************************************************************************** */
/* Sectors represent the physical sectors of the storage memory (space!).
* Simon Lothar says that there are 27 entries for them (or 25 "not on the
* AU" in the other documentation, whatever that means).
*
* Their special nibble is either 0x04 or 0x00, I don't know why yet.
* Here is their subheader structure: */
struct storage_sector {
/* the sector start address - 0xFF */
uint32_t startaddr;
/* the sector ID - because for some reason, fragments won't use the uuid */
uint32_t logical_sector_number;
};
/* ************************************************************************** */
/* Directories */
/* ************************************************************************** */
/* After the sectors come the directories.
*
* Their special nibble is either 0x05 if active or 0x00 if deleted.
* Here is their subheader structure: */
struct storage_directory {
/* the directory reference - looks unusable */
uint32_t directory_reference;
/* the name (FONTCHARACTER-encoded) */
FONTCHARACTER name[12];
};
/* ************************************************************************** */
/* Files */
/* ************************************************************************** */
/* After the directories come the files (interrupted by fragments - see after).
*
* Their special nibble have the same meaning that for directories.
* Here is their subheader structure: */
struct storage_file {
/* the directory reference
* - is `storage_entrytype_directory` if the file is in a subdirectory.
* - is 0xFFFF otherwise. */
uint16_t directory_reference;
/* the directory number - should be read only if is in a subdirectory. */
uint16_t directory_number;
/* the name (FONTCHARACTER-encoded) */
FONTCHARACTER name[12];
};
/* ************************************************************************** */
/* File fragments */
/* ************************************************************************** */
/* After each file entry comes the corresponding fragments entries.
* Fragments are in fact links to the sectors, with some more info.
*
* Their special nibble have the same meaning that for files... but are not
* always accurate, so only check on files.
* Here is their subheader structure: */
struct storage_fragment {
/* the file ID */
uint32_t file_uuid;
/* the file type (probably detected when the file is transferred):
* - 0x01 for an unknown type;
* - 0x02 for an add-in (G1A);
* - 0x06 for an MCS archive (G1M);
* - 0x2E for an MCS archive with setup (G1R).
*
* why is it here and not in the file entry data? you've got a point. */
uint16_t file_type;
/* the fragment count */
uint16_t fragment_count;
/* the fragment number */
uint16_t fragment_id;
/* the sector id that the fragment is linked to */
uint16_t fragment_sector_id;
/* offset of the used bytes in sector */
uint16_t used_bytes_offset;
/* number of used bytes in sector */
uint16_t used_bytes;
};
#endif /* LIBG1M_FORMAT_STORAGE_H */

View File

@ -8,6 +8,9 @@
/* */
/* ************************************************************************** */
#include <libg1m/internals.h>
#define SUB(V, TYPE) \
case storage_entrytype_##TYPE:; \
struct storage_##TYPE *V = (struct storage_##TYPE*)&entry.raw_subheader;
/**
* g1m_parse_storage:
@ -23,12 +26,89 @@ int g1m_parse_storage(g1m_t *handle, FILE *stream,
struct standard_header *std)
{
(void)std;
handle->type = 0x00;
/* skip the first 0x270000 - 0x20 bytes */
SKIP(0x270000 - sizeof(struct standard_header))
/* then read and stuff... not yet. */
log_error("Storage files are not managed yet.");
handle->type = 0x00;
/* read */
log_info("Storage memory!");
/* read the entries */
#if LOGLEVEL <= ll_info
for (int id = 1;; id++) {
#else
for (;;) {
#endif
/* read the entry */
DREAD(entry, storage_entry)
if (entry.type == 0xFFFF)
break;
entry.type = be16toh(entry.type);
entry.uuid = be16toh(entry.uuid);
/* read it */
int special = (entry.type & 0xF000) >> 12;
switch (entry.type & 0xFFF) {
SUB(sh, sector)
int unused = (sh->logical_sector_number == 0xFFFFFFFF);
log_info("[%02d,%02" PRIu16 "] Is a%ssector.", id, entry.uuid,
(unused) ? "n unused " : " ");
log_info("- Starts at address 0x%08" PRIx32,
be32toh(sh->startaddr));
#if LOGLEVEL <= ll_info
if (!unused) log_info("- Logical number: 0x%08" PRIu32,
be32toh(sh->logical_sector_number));
#endif
break;
SUB(dh, directory)
log_info("[%02d,%02" PRIu16 "] Is a %s directory.", id, entry.uuid,
(special == 0x05) ? "deleted" : "active");
#if LOGLEVEL <= ll_info
FONTCHARACTER rawdir[13]; rawdir[12] = 0;
memcpy(rawdir, dh->name, 12 * sizeof(FONTCHARACTER));
{
int i;
for (i = 0; rawdir[i] != 0xffff && i < 12; i++)
rawdir[i] = be16toh(rawdir[i]);
rawdir[i] = 0;
}
char dirname[25]; g1m_fcstombs(dirname, rawdir, 0);
log_info("- Directory name: %s", dirname);
#endif
break;
SUB(fh, file)
log_info("[%02d,%02" PRIu16 "] Is a %s file.", id, entry.uuid,
(special == 0x05) ? "deleted" : "active");
#if LOGLEVEL <= ll_inf
FONTCHARACTER rawname[13]; rawname[12] = 0;
memcpy(rawname, fh->name, 12 * sizeof(FONTCHARACTER));
{
int i;
for (i = 0; rawname[i] != 0xffff && i < 12; i++)
rawname[i] = be16toh(rawname[i]);
rawname[i] = 0;
}
char name[25]; g1m_fcstombs(name, rawname, 0);
log_info("- File name: %s", name);
#endif
log_info("- Directory ref: %" PRIu16,
be16toh(fh->directory_reference));
log_info("- Directory num: %" PRIu16,
be16toh(fh->directory_number));
break;
SUB(fgh, fragment)
log_info("[%02d,%02" PRIu16 "] Is a fragment.", id, entry.uuid);
log_info("- Points at sector #%" PRIu16,
be16toh(fgh->fragment_sector_id));
log_info("- Is %" PRIu16 "/%" PRIu16
" (%" PRIu16 "o at offset 0x%04" PRIx16 ")",
be16toh(fgh->fragment_id), be16toh(fgh->fragment_count),
be16toh(fgh->used_bytes), be16toh(fgh->used_bytes_offset));
break;
default:
log_info("[%02d,%02" PRIu16 "] Is unknown.", id, entry.uuid);
}
}
/* no error */
return (0);

View File

@ -120,7 +120,7 @@ struct ext_corresp {
/* Extension correspondances */
static struct ext_corresp ext_types[] = {
/* raw MCS */
/* storage files */
{"g1s", "Storage file", g1m_platform_none, g1m_type_storage},
/* fx types with non-checked header */