cake
/
libg1m
Archived
1
0
Fork 0

Corrected comment style, added some Casemul documentation (unfinished)

This commit is contained in:
Thomas Touhey 2017-03-01 03:46:18 +01:00
parent 14831b57f5
commit 160a8427f2
10 changed files with 387 additions and 173 deletions

View File

@ -35,7 +35,7 @@ typedef int g1m_color_t;
# define g1m_color_yellow 0x6
# define g1m_color_white 0x7
/* And some macros to help you out: */
/* And some macros to help you out: */
# define g1m_marker_color(C) (((C) & 0xf0) >> 4)
# define g1m_char_color(C) ((C) & 0xf)
# define g1m_character_color(C) g1m_char_color(C)

View File

@ -53,6 +53,22 @@
//# include <libg1m/format/fxi.h>
/* ************************************************************************** */
/* The Casemul format */
/* ************************************************************************** */
/* Casemul is a CASIO emulator for Microsoft Windows. It is an old software
* which was not updated since 2005. It can import and export other files,
* but save its files in its own format, which use the .cas extension
* (like the CASIOLINK format, but the two formats are completely different).
*
* It starts with a four-letter magic string, "ACFS". In fact, it is
* "CASF", like in "CasFile", the name of the real header. */
# define CASEMUL_MAGIC "ACFS"
/* Discover the rest in its own header: */
# include <libg1m/format/casemul.h>
/* ************************************************************************** */
/* The G1M/STD format */
/* ************************************************************************** */
/* Since around 2004, CASIO has adopted a single "superformat"; we call it

View File

@ -0,0 +1,198 @@
/* *****************************************************************************
* libg1m/format/casemul.h -- the Casemul 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_CASEMUL_H
# define LIBG1M_FORMAT_CASEMUL_H
# pragma pack(1)
/* Casemul files are made of an overall header, a source part and an
* optional compiled part. One thing to know is that every header has an
* internal header, which always has this structure: */
struct casemul_internal_header {
/* this type was made using `MAKELONG`: you have to reverse the bytes in
* each word (e.g. AC-FS -> CA-SF). */
char type[4];
/* version (more or less 0xMMmm, where MM is the major and mm the minor) */
uint32_t version;
/* header size */
uint32_t size;
};
/* The multi-byte values are always little-endian, expected from the
* values made with `MAKELONG` (like the internal header type, which, in the
* source, is a DWORD), because its funnier. */
/* TODO: The separator between header and source header:
* "\xFD\xB1\x7E" "\0\0\0\0\0\0\0"
* "\x18" "\0\0\0\0\0\0\0"
*/
/* ************************************************************************** */
/* Overall, source and compiled headers */
/* ************************************************************************** */
/* The overall header contains information about the other sections, and the
* current state of the file (whether it contains the compiled part or not).
*
* Its internal header ID is "CAFS" (ACFS, used as the magic string).
* The expected version is 1.00. */
# define casemul_compiled 0x80 /* if the compiled program is there */
struct casemul_header {
/* the flags */
uint8_t flags;
/* offset of the sources */
uint32_t source_offset;
/* compiled program offset */
uint32_t compiled_offset;
/* some alignment? */
uint8_t _align[3];
};
/* At the beginning of the source part, we find the source header.
* The source part contains the programs, pictures, matrixes and lists as four
* blocks, uncompiled.
*
* Its internal header ID is "SRCE" (RSEC).
* The expected version is 1.00. */
struct casemul_source_header {
/* number of program records in the program block */
uint8_t programs;
/* number of picture records in the program block */
uint8_t pictures;
/* number of matrix records in the program block */
uint8_t matrixes;
/* number of list records in the list block */
uint8_t lists;
/* program block offset */
uint32_t programs_offset;
/* picture block offset (length of the file before) */
uint32_t pictures_offset;
/* matrix block offset */
uint32_t matrixes_offset;
/* list block offset */
uint32_t list_offset;
/* main program ID */
uint8_t program_id;
/* alignment */
uint8_t _align[3];
};
/* At the beginning of the compiled part, we find the compiled header.
* The compilation process is unknown (yet to read the sources to find out
* what it is).
*
* Its internal header ID is "COMP" (OCPM).
* The expected version is 1.00. */
struct casemul_comp_header {
/* the number of instructions (size of the part) */
uint32_t instructions_count;
};
/* ************************************************************************** */
/* Record */
/* ************************************************************************** */
/* For each element, there is record, with a header and a subheader. The
* record header cannot easily be expressed as a structure, so here it is, in
* the form of a comment:
*
* uint32_t name_length;
* The name length.
* uint8_t name[name_length];
* The name.
* uint32_t length;
* The subheader+data length.
*
* Then expect an internal header, part of the subheader, that expresses the
* type of it (expected version for all of them is 1.00). */
/* ************************************************************************** */
/* Program */
/* ************************************************************************** */
/* A program has type "PROG" (RPGO). Its subheader is the following: */
struct casemul_prog_header {
/* program length after Casemul encoding */
uint32_t length;
};
/* Casemul makes use of tokens instead of FONTCHARACTERs or Unicode - this
* should be documented in the FONTCHARACTER reference. */
/* ************************************************************************** */
/* Picture */
/* ************************************************************************** */
/* A picture has type "PICT" (IPTC), and has the following subheader: */
struct casemul_pict_header {
/* size */
uint8_t w, h;
/* ... aaaaand alignment. (you know, unchecked theory?) */
uint8_t _align[2];
};
/* Also, pixels are organized per _column_; this comes from the original code:
*
* BYTE m_TabPixels[DATAPICTURE_CX][DATAPICTURE_CY];
*
* Notice that DATAPICTURE_CX and DATAPICTURE_CY are actually macros,
* which means there are always 128x64 pixels (or at least that Casemul
* will only be able to open 128x64 pictures)... */
/* ************************************************************************** */
/* Matrix */
/* ************************************************************************** */
/* A matrix has type "MTRX" (TMXR) and its its subheader has the following
* structure: */
struct casemul_mtrx_header {
/* number of lines and columns
* actually int-s in the original code... */
uint32_t lines, columns;
};
/* TODO: describe the matrix format more precisely. */
/* ************************************************************************** */
/* List */
/* ************************************************************************** */
/* A list has type "LIST" (ILTS) and has the following subheader structure: */
struct casemul_list_header {
/* number of lines
* actually int-s in the original code... */
uint32_t lines;
};
/* TODO: describe the list format more precisely. */
# pragma pack()
#endif /* LIBG1M_FORMAT_CASEMUL_H */

View File

@ -21,12 +21,12 @@
# include <stdint.h>
# pragma pack(1)
/* Add-ins are compiled programs. They only have one G1M part,
* These add-ins usually have the `g1a`, `g3a` or `c1a` extension. */
/* Add-ins are compiled programs. They only have one G1M part,
* These add-ins usually have the `g1a`, `g3a` or `c1a` extension. */
/* ************************************************************************** */
/* Legacy fx systems add-ins (G1A) */
/* ************************************************************************** */
/* G1A subheader is the following: */
/* G1A subheader is the following: */
# define G1A_ICON_WIDTH 30
# define G1A_ICON_HEIGHT 17
@ -76,15 +76,15 @@ struct g1a_subheader {
uint8_t _spacing7[0xc];
};
/* Then the G1A file will just contain the add-in code and stop. */
/* Then the G1A file will just contain the add-in code and stop. */
/* ************************************************************************** */
/* Classpad and Prizm add-ins (C1A, G3A) */
/* ************************************************************************** */
/* The two formats are identified the same way in the standard header, but
* some of the header parts are different, until the header just stops being
* the same.
/* The two formats are identified the same way in the standard header, but
* some of the header parts are different, until the header just stops being
* the same.
*
* Here's the common parts of their headers: */
* Here's the common parts of their headers: */
struct addin_cp_subheader {
/* byte checksum: 0x0000 to 0x001F (standard header)
@ -145,8 +145,8 @@ struct addin_cp_subheader {
uint8_t stamp[14];
};
/* Then from here, the two formats diverge.
* G3A subheader goes like this: */
/* Then from here, the two formats diverge.
* G3A subheader goes like this: */
# define G3A_ICON_WIDTH 92
# define G3A_ICON_HEIGHT 64
@ -178,7 +178,7 @@ struct g3a_subheader {
uint8_t unselected_icon_image[0x3000];
};
/* And the C1A header goes like this: */
/* And the C1A header goes like this: */
# define C1A_ICON_WIDTH 46
# define C1A_ICON_HEIGHT 30

View File

@ -20,30 +20,30 @@
# define LIBG1M_FORMAT_STD_EACT_H
# include <stdint.h>
/* E-Activities are the format CASIO uses for in-calc documents.
* It is the funniest subformat the the libg1m can parse.
/* E-Activities are the format CASIO uses for in-calc documents.
* It is the funniest subformat the the libg1m can parse.
*
* There is only one part for e-activities.
* The overall header has two zones:
* - the special header, that keeps the global info;
* - the setup area, that keeps one part of the calculator setup.
* There is only one part for e-activities.
* The overall header has two zones:
* - the special header, that keeps the global info;
* - the setup area, that keeps one part of the calculator setup.
*
* There are several types for E-Activies, identified by the extensions
* CASIO give them.
* The E-Act version in the header is 0x10100 for g1e, 0x10200 for g2e,
* and 0x10400 for g3e. */
* There are several types for E-Activies, identified by the extensions
* CASIO give them.
* The E-Act version in the header is 0x10100 for g1e, 0x10200 for g2e,
* and 0x10400 for g3e. */
# define EACT_G1E 0x10100
# define EACT_G2E 0x10200
# define EACT_G3E 0x10400
/* The differences between these formats are the following:
* - On g1e, the OS version is always 0x5061636B, where on g2e/g3e,
* the OS version is the version of the OS on which the file was written.
* - On g1e/g2e, the setup directory is 0x10-bytes long, where on g3e,
* the setup directory is 0x2C-bytes long.
/* The differences between these formats are the following:
* - On g1e, the OS version is always 0x5061636B, where on g2e/g3e,
* the OS version is the version of the OS on which the file was written.
* - On g1e/g2e, the setup directory is 0x10-bytes long, where on g3e,
* the setup directory is 0x2C-bytes long.
*
* So the main header is: */
* So the main header is: */
struct eact_header {
/* the filesize */
@ -59,8 +59,8 @@ struct eact_header {
uint32_t os_version;
};
/* And now, the funniest part: the content.
* So a content has this header: */
/* And now, the funniest part: the content.
* So a content has this header: */
struct eact_contentheader {
/* content type: @EACT, @RUNMAT, ... */
@ -76,18 +76,18 @@ struct eact_contentheader {
uint8_t align2[4];
};
/* There are several types of contents.
* The most basic one is also called "@EACT".
* It has this content subheader: */
/* There are several types of contents.
* The most basic one is also called "@EACT".
* It has this content subheader: */
struct eact_eactheader {
/* line count */
uint32_t line_count;
};
/* And after, lines come. First of all, there is a line descriptor table,
* that contain the line type and the line offset from the subheader begin.
* A line type can have these types: */
/* And after, lines come. First of all, there is a line descriptor table,
* that contain the line type and the line offset from the subheader begin.
* A line type can have these types: */
enum eact_linetype {
/* contains a calculation */
@ -113,7 +113,7 @@ enum eact_linetype {
eact_ltype_code = 0x82
};
/* And here's the line descriptor structure: */
/* And here's the line descriptor structure: */
struct line_descriptor {
/* the entry type */
@ -123,12 +123,12 @@ struct line_descriptor {
uint32_t entry_offset :24;
};
/* And there is only one content after the main header, and it's a content
* of EACT type. But hey, why the heck have we defined several types and stuff?
* Well, that's the funniest thing of E-Activities:
/* And there is only one content after the main header, and it's a content
* of EACT type. But hey, why the heck have we defined several types and stuff?
* Well, that's the funniest thing of E-Activities:
*
* they are RECURSIVE. [drama alert]
* they are RECURSIVE. [drama alert]
*
* Which means in each node, there can be a content to parse. */
* Which means in each node, there can be a content to parse. */
#endif /* LIBG1M_FORMAT_STD_EACT_H */

View File

@ -21,18 +21,18 @@
# include <libg1m.h>
# pragma pack(1)
/* Function keys are the little boxes at the bottom with text in it, to tell
* you what you're going to access if you press F1-F6. */
/* Function keys are the little boxes at the bottom with text in it, to tell
* you what you're going to access if you press F1-F6. */
/* ************************************************************************** */
/* G1N - Function-keys files for fx calculators */
/* ************************************************************************** */
/* In G1Ns, function keys are 19x8 1-bit with fill bits images.
/* In G1Ns, function keys are 19x8 1-bit with fill bits images.
*
* TODO: it is unknown yet how to identify G1N files, as no non-community-made
* one of them was found and the calculator software just skips
* StandardHeader. It has to be found for a correct integration in libg1m!
* TODO: it is unknown yet how to identify G1N files, as no non-community-made
* one of them was found and the calculator software just skips
* StandardHeader. It has to be found for a correct integration in libg1m!
*
* The format looks a lot like G1L files. The header is the following: */
* The format looks a lot like G1L files. The header is the following: */
# define FKEY_WIDTH 24
# define FKEY_HEIGHT 8
@ -47,20 +47,20 @@ struct g1n_subheader {
uint16_t fkey_count;
};
/* Then there is a table of 16-bits offsets (iconXXX - icon0), then the icons.
* The first "icon" is in fact the name of the language. */
/* Then there is a table of 16-bits offsets (iconXXX - icon0), then the icons.
* The first "icon" is in fact the name of the language. */
/* ************************************************************************** */
/* G3L-N - Function-keys files for CG calculators */
/* ************************************************************************** */
/* G3L-N have exactly the same header and subheader as G3Ls, except
* the magic field is "0201" and not "0401" like for "normal" G3Ls.
/* G3L-N have exactly the same header and subheader as G3Ls, except
* the magic field is "0201" and not "0401" like for "normal" G3Ls.
*
* TODO: it is unknown yet how to identify G3N files using the StandardHeader,
* as no non-community-made one of them was found and the calculator software
* just skips StandardHeader. It has to be found for a correct integration
* in libg1m!
* TODO: it is unknown yet how to identify G3N files using the StandardHeader,
* as no non-community-made one of them was found and the calculator software
* just skips StandardHeader. It has to be found for a correct integration
* in libg1m!
*
* In G3L-Ns, function keys are 64x24 1-bit images. */
* In G3L-Ns, function keys are 64x24 1-bit images. */
# define FKEY3_WIDTH 64
# define FKEY3_HEIGHT 24

View File

@ -24,7 +24,7 @@
/* ************************************************************************** */
/* G1L - Language files for fx calculators */
/* ************************************************************************** */
/* It all starts with a header: */
/* It all starts with a header: */
struct g1l_subheader {
/* identifier: is "PowerUSB" on original things */
@ -41,19 +41,19 @@ struct g1l_subheader {
uint16_t message_count;
};
/* Then comes a list of offsets, and the messages.
/* Then comes a list of offsets, and the messages.
*
* Each element of the offsets list is 16-bytes long.
* It is relative to the first element (which starts right after the
* offsets list - no alignment).
* Each element of the offsets list is 16-bytes long.
* It is relative to the first element (which starts right after the
* offsets list - no alignment).
*
* The messages are null-terminated - once you get the offsets, you get
* them completely. */
* The messages are null-terminated - once you get the offsets, you get
* them completely. */
/* ************************************************************************** */
/* G3L - Language files for Prizm */
/* ************************************************************************** */
/* Thanks to amazonka for his (minimalist) description of the G3L format
* at Cemetech. So the G3L format starts off with a header: */
/* Thanks to amazonka for his (minimalist) description of the G3L format
* at Cemetech. So the G3L format starts off with a header: */
struct g3l_subheader {
/* a checksum */
@ -110,8 +110,8 @@ struct g3l_subheader {
uint8_t undocumented4[308];
};
/* Then there is something amazonka names the "executable code section".
* This is in fact the message zone. */
/* Then there is something amazonka names the "executable code section".
* This is in fact the message zone. */
struct g3l_lang_header {
/* sequence: '4C 59 37 35 35 00 00 00 02' (LY755 ) */
@ -127,17 +127,17 @@ struct g3l_lang_header {
uint8_t unused2[2];
};
/* Then we have offsets of all messages (4 bytes each),
* then messages themselves, zero-terminated.
/* Then we have offsets of all messages (4 bytes each),
* then messages themselves, zero-terminated.
*
* The four last bytes of the files are a little footer, which is: */
* The four last bytes of the files are a little footer, which is: */
struct g3l_footer {
/* copy of the first checksum in the subheader */
uint32_t checksum;
};
/* This footer is not counted as part of the file. */
/* This footer is not counted as part of the file. */
# pragma pack()
#endif /* LIBG1M_FORMAT_STD_LANG_H */

View File

@ -21,22 +21,22 @@
# include <stdint.h>
# pragma pack(1)
/* MCS is the main filesystem on CASIO calculators. They contain settings,
* programs, lists, pictures, captures, matrixes, and other data CASIO
* calculators own.
* Keep in mind that all numbers in the MCS format are BCD-encoded.
* Because of some precision issue (0.3), we'll deliver them to the user as is.
/* MCS is the main filesystem on CASIO calculators. They contain settings,
* programs, lists, pictures, captures, matrixes, and other data CASIO
* calculators own.
* Keep in mind that all numbers in the MCS format are BCD-encoded.
* Because of some precision issue (0.3), we'll deliver them to the user as is.
*
* MCS files have a group, a directory, a name and a type. This type depends
* on the group it's in. So for example, the 0xFE type in the 'S-SHEET' group
* will correspond to a spreadsheet! In an MCS G1M file, files are more or less
* regrouped by their group (but sometimes they're not, there are several
* 'PROGRAM' groups with one element for example).
* MCS files have a group, a directory, a name and a type. This type depends
* on the group it's in. So for example, the 0xFE type in the 'S-SHEET' group
* will correspond to a spreadsheet! In an MCS G1M file, files are more or less
* regrouped by their group (but sometimes they're not, there are several
* 'PROGRAM' groups with one element for example).
*
* The `number` field in the Standard Header corresponds to the total number
* of MCS files, not group instances!
* The `number` field in the Standard Header corresponds to the total number
* of MCS files, not group instances!
*
* Each group instance have a header, and here it is: */
* Each group instance have a header, and here it is: */
struct mcs_subheader {
/* group name (e.g. "PROGRAM", zero padded) */
@ -46,8 +46,8 @@ struct mcs_subheader {
uint32_t subcount;
};
/* Then follows the files, with their headers and contents.
* And the header iiiiiiis: */
/* Then follows the files, with their headers and contents.
* And the header iiiiiiis: */
struct mcs_fileheader {
/* the directory name (zero-padded).*/
@ -68,8 +68,8 @@ struct mcs_fileheader {
# pragma pack()
/* Beneath the file header, the file have different structures according to
* their group name and MCS type. Pick your poison, once again! */
/* Beneath the file header, the file have different structures according to
* their group name and MCS type. Pick your poison, once again! */
# include <libg1m/format/mcs/list.h>
# include <libg1m/format/mcs/matrix.h>

View File

@ -23,18 +23,18 @@
/* ************************************************************************** */
/* G3P: pictures for Prizm */
/* ************************************************************************** */
/* G3P are pictures for fx-CG. They only have one part.
* This mysteries over this format have been unraveled by many, but I'm using
* Simon Lothar's documentation and Kerm Martian's articles.
/* G3P are pictures for fx-CG. They only have one part.
* This mysteries over this format have been unraveled by many, but I'm using
* Simon Lothar's documentation and Kerm Martian's articles.
*
* Some color depth things: */
* Some color depth things: */
enum g3p_colorsize {
g3p_color_4bit = 0x03,
g3p_color_16bit = 0x10
};
/* So, after the header, here is the G3P subheader: */
/* So, after the header, here is the G3P subheader: */
struct g3p_subheader {
/* some magic sequence: "CP0100Ly755"
@ -57,9 +57,9 @@ struct g3p_subheader {
uint8_t undocumented_gap[124];
};
/* What is after the G3P subheader is the image (data).
/* What is after the G3P subheader is the image (data).
*
* The image has a header, some data and a footer. Here is the header: */
* The image has a header, some data and a footer. Here is the header: */
struct g3p_imageheader {
/* magic sequence? is: 0x00, 0x01, 0x00, 0x00 */
@ -87,33 +87,33 @@ struct g3p_imageheader {
uint32_t data_size;
};
/* Then there is the image data and the footer.
/* Then there is the image data and the footer.
*
* At the beginning of the image data, there is a 2-byte ID.
* 0x3c1b is the ID for "Casio Provided" images with no footers (?).
* At the beginning of the image data, there is a 2-byte ID.
* 0x3c1b is the ID for "Casio Provided" images with no footers (?).
*
* The image is deflated using the DEFLATE algorithm.
* The image is deflated using the DEFLATE algorithm.
*
* For some images, CASIO added some obfuscation. To check if the image is
* encrypted, according to syscalls, you have to check standard header data.
* Image is encrypted if:
* For some images, CASIO added some obfuscation. To check if the image is
* encrypted, according to syscalls, you have to check standard header data.
* Image is encrypted if:
*
* [0x1C] != [0x08] + [0x12] + [0x13] + 0x7B
* [0x1C] != [0x08] + [0x12] + [0x13] + 0x7B
*
* Which, simplified and with our structures, is:
* Which, simplified and with our structures, is:
*
* (std.obfuscated + 8) & 0xff != (std.filesize & 0xff00) >> 8
* (std.obfuscated + 8) & 0xff != (std.filesize & 0xff00) >> 8
*
* then the deflated image is encrypted.
* then the deflated image is encrypted.
*
* If this is the case, before passing the data to the INFLATE algorithm,
* you have to apply this on each byte of the deflated image:
* If this is the case, before passing the data to the INFLATE algorithm,
* you have to apply this on each byte of the deflated image:
*
* 0b76543210 -> 0b21076543,
* which, in C, is: (byte >> 3) | ((byte & 0x7) << 5)
* 0b76543210 -> 0b21076543,
* which, in C, is: (byte >> 3) | ((byte & 0x7) << 5)
*
* The footer contains the Adler32 checksum of the raw and unobfuscated data.
* Here it is: */
* The footer contains the Adler32 checksum of the raw and unobfuscated data.
* Here it is: */
struct g3p_imagefooter {
/* checksum */
@ -123,7 +123,7 @@ struct g3p_imagefooter {
/* ************************************************************************** */
/* C2P: Images for Classpads */
/* ************************************************************************** */
/* C2P are images for fx-CP400 calculators. It starts of with this header: */
/* C2P are images for fx-CP400 calculators. It starts of with this header: */
struct c2p_subheader {
/* magic field: "CC0100" */
@ -166,11 +166,11 @@ struct c2p_subheader {
uint32_t unknown_size3;
};
/* Then there is the zlib header with default compression.
* The pixels format is R5G6B5.
/* Then there is the zlib header with default compression.
* The pixels format is R5G6B5.
*
* After the image, there is a footer, which is mainly undocumented, but
* here is what we've got: */
* After the image, there is a footer, which is mainly undocumented, but
* here is what we've got: */
struct c2p_footer {
/* "0100", again */

View File

@ -19,23 +19,23 @@
#ifndef LIBG1M_FORMAT_STD_STORAGE_H
# define LIBG1M_FORMAT_STD_STORAGE_H
/* Storage backup files (G1S) contain backups of the storage memory.
* It corresponds exactly to the on-calc storage memory structure.
/* 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.
* 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. */
* 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: */
/* 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 */
@ -51,9 +51,9 @@ struct storage_entry {
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: */
/* 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,
@ -62,39 +62,39 @@ enum storage_entry_type {
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.
/* 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).
* 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.
* 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.
* 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. */
* 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.
/* 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)
* 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: */
* 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 */
@ -108,10 +108,10 @@ struct storage_sector {
/* ************************************************************************** */
/* Directories */
/* ************************************************************************** */
/* After the sectors come the directories.
/* After the sectors come the directories.
*
* Their special nibble is either 0x05 if active or 0x00 if deleted.
* Here is their subheader structure: */
* 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 */
@ -125,10 +125,10 @@ struct storage_directory {
/* ************************************************************************** */
/* Files */
/* ************************************************************************** */
/* After the directories come the files (interrupted by fragments - see after).
/* 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: */
* 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?) */
@ -142,15 +142,15 @@ struct storage_file {
/* ************************************************************************** */
/* File fragments */
/* ************************************************************************** */
/* After each file entry comes the corresponding fragments entries.
* Fragments are in fact links to the sectors, with some more info.
/* 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!
* 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: */
* 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,
@ -159,8 +159,8 @@ enum storage_file_type {
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: */
/* 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 */