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/include/libg1m/format/storage.h

186 lines
7.3 KiB
C

/* *****************************************************************************
* libg1m/format/storage.h -- the G1M storage file format description.
* 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/>.
* ************************************************************************** */
#ifndef LIBG1M_FORMAT_STORAGE_H
# define LIBG1M_FORMAT_STORAGE_H
/* 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
* (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.
*
* 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 number of the entry
* if this field is 0x00, just ignore the entry.
* we don't know why entries with this field set to 0x00 exist...
* (probably backups?) */
uint16_t id;
/* 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,
};
/* The special nibble is usually zero when deleted, and non-zero when active.
* According to Simon Lothar, this is because it is possible to clear bits
* on the flash by flashwriting a short value only; but when it comes to
* set bits, it becomes more tricky.
*
* This is also why optimizing is not done straight away (to save the flash
* a little).
*
* The list can have to 0x800 entries, and occupies the first sector.
* Simon Lothar says the list can expand to the second sector (which is used
* only if there is no space in the index sector or the other data sectors).
* Entries with the 0xFFFF type should not be read.
*
* Some entry types can have parents. In this case, they have parent type,
* and parent number fields. This is because elements with different types
* follow different numerations; so the type field is here on which numeration
* to search for the member. If the parent type is 0xFFFF (or -1, as some say),
* then there is no parent.
*
* For now, only directories as parents for files have been encountered. */
/* ************************************************************************** */
/* Sectors */
/* ************************************************************************** */
/* Sectors represent the physical sectors of the storage memory (space!).
* They are 64 KiB large.
*
* Simon Lothar says that there are 27 entries for them (or 14 on the AU models
* because of australian exam regulations). If the logical number
* is 0xFFFFFFFF, the sector is unused. (sometimes the logical number field
* contains gibberish, I don't know why yet)
*
* Their special nibble is either 0x04 or 0x00, the signification of it is not
* known to me yet. Here is their subheader structure: */
struct storage_sector {
/* the sector start address - 0xFF */
uint32_t startaddr;
/* the sector ID - probably not using the UUID so sectors can
* not be set as parent nodes :) */
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 parent type and id */
uint16_t parent_type;
uint16_t parent_id;
/* 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 parent type and id (not functional?) */
uint16_t parent_type;
uint16_t parent_id;
/* 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!
*
* The first fragment corresponding to a file contain this file's type,
* probably detected when the file is transferred. Here are the
* known values: */
enum storage_file_type {
g1m_storage_filetype_unknown = 0x01,
g1m_storage_filetype_addin = 0x02, /* G1A */
g1m_storage_filetype_mcs = 0x06, /* G1M */
g1m_storage_filetype_g2r = 0x2E, /* G1R */
};
/* Why is the file type here and not in the file header? I don't know.
* And here is the fragments' subheader structure: */
struct storage_fragment {
/* the parent (file node) type and id */
uint16_t parent_type;
uint16_t parent_id;
/* the file type */
uint16_t file_type;
/* the fragment count and id */
uint16_t fragment_count;
uint16_t fragment_id;
/* the sector id that the fragment is linked to */
uint16_t fragment_sector_id;
/* number and offset in the sector of the fragment's bytes */
uint16_t data_offset;
uint16_t data_length;
};
#endif /* LIBG1M_FORMAT_STORAGE_H */