aboutsummaryrefslogtreecommitdiff
path: root/include/libcasio/format/storage.h
blob: 689a58882d4c2297f7f8f1812c8a3bb250e8ec4d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/* ****************************************************************************
 * 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 spec# include "../cdefs.h"ial 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 */