cake
/
libcasio
Archived
1
1
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.
libcasio/include/libcasio/format/storage.h

194 lines
7.1 KiB
C

/* ****************************************************************************
* libcasio/format/storage.h -- the storage file format description.
* Copyright (C) 2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libcasio.
* libcasio 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.
*
* libcasio 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 libcasio; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************* */
#ifndef LIBCASIO_FORMAT_STORAGE_H
# define LIBCASIO_FORMAT_STORAGE_H
# include "../cdefs.h"
# pragma pack(1)
CASIO_BEGIN_NAMESPACE
/* 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
* (this is the mapped location of the SMEM in real fx-9860 calculators),
* then it has the same structure than the one used by the calculator.
*
* These files are not managed by the calculator 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: */
typedef struct casio_storage_entry_s {
/* the type number - see below */
casio_uint16_t casio_storage_entry_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?) */
casio_uint16_t casio_storage_entry_id;
/* the raw subheader */
casio_uint8_t casio_storage_entry_raw_subheader[28];
} casio_storage_entry_t;
/* 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: */
# define storage_entrytype_directory 0x110
# define storage_entrytype_file 0x120
# define storage_entrytype_fragment 0x130
# define storage_entrytype_sector 0x200
/* 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 contain up 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: */
typedef struct casio_storage_sector_s {
/* the sector start address - 0xFF */
casio_uint32_t casio_storage_sector_startaddr;
/* the sector ID - probably not using the UUID so sectors can
* not be set as parent nodes :) */
casio_uint32_t casio_storage_sector_logical_sector_number;
} casio_storage_sector_t;
/* ---
* Directories.
* --- */
/* After the sectors come the directories.
*
* Their special nibble is either 0x05 if active or
* 0x00 if deleted. Here is their subheader structure: */
typedef struct casio_storage_directory_s {
/* the parent type and id */
casio_uint16_t casio_storage_directory_parent_type;
casio_uint16_t casio_storage_directory_parent_id;
/* the name (FONTCHARACTER-encoded) */
casio_uint16_t casio_storage_directory_name[12];
} casio_storage_directory_t;
/* ---
* 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: */
typedef struct casio_storage_file_s {
/* the parent type and id (not functional?) */
casio_uint16_t casio_storage_file_parent_type;
casio_uint16_t casio_storage_file_parent_id;
/* the name (FONTCHARACTER-encoded) */
casio_uint16_t casio_storage_file_name[12];
} casio_storage_file_t;
/* ---
* File fragments.
* --- */
/* After each file entry comes the corresponding fragments entries.
* Fragments are in fact links to the sectors, with some more information.
*
* 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/created/whatever. Here are
* the known values: */
# define casio_storage_filetype_regular 0x01
# define casio_storage_filetype_unknown casio_storage_filetype_regular
# define casio_storage_filetype_addin 0x02 /* G1A */
# define casio_storage_filetype_mcs 0x06 /* G1M */
# define casio_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: */
typedef struct casio_storage_fragment_s {
/* the parent (file node) type and id */
casio_uint16_t casio_storage_fragment_parent_type;
casio_uint16_t casio_storage_fragment_parent_id;
/* the file type */
casio_uint16_t casio_storage_fragment_file_type;
/* the fragment count and id */
casio_uint16_t casio_storage_fragment_count;
casio_uint16_t casio_storage_fragment_id;
/* the sector id that the fragment is linked to */
casio_uint16_t casio_storage_fragment_sector_id;
/* number and offset in the sector of the fragment's bytes */
casio_uint16_t casio_storage_fragment_data_offset;
casio_uint16_t casio_storage_fragment_data_length;
} casio_storage_fragment_t;
CASIO_END_NAMESPACE
# pragma pack()
#endif /* LIBCASIO_FORMAT_STORAGE_H */