208 lines
7.7 KiB
C
208 lines
7.7 KiB
C
/* *****************************************************************************
|
|
* libg1m/format/cas.h -- the older CAS 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_CAS_H
|
|
# define LIBG1M_FORMAT_CAS_H
|
|
# include <stdint.h>
|
|
# pragma pack(1)
|
|
|
|
/* See `libg1m/format.h` for general information about what the CASIOLINK
|
|
* format is.
|
|
*
|
|
* The CASIOLINK file format is linked to how the legacy (CAS) protocol works:
|
|
* one-byte packets are sent between the two machines (for initiating
|
|
* communication, ACKing, NAKing, ...), unless the sent/receiving byte is
|
|
* the double-colon ':' (0x3A) -- then it is the beginning of something
|
|
* that is more than one-byte long. CAS files do not include the one-byte
|
|
* packets, or repeated headers/parts (because of bad checksum or timeouts,
|
|
* for example).
|
|
*
|
|
* Actually, there are three main things that start with a ':'. The main type
|
|
* is a header, that describes the content that follows. A content can have
|
|
* no content part (e.g. END packet), one content part (e.g. programs), or
|
|
* more (e.g. width*height content parts for lists and matrixes, which
|
|
* represent the individual cells). These content parts have different formats
|
|
* according to the global content part.
|
|
*
|
|
* But I told you there were three things. The third is a little subtle:
|
|
* one header can correspond to several contents. Then we have what we
|
|
* call the CAS file*s* part (or heads part).
|
|
* An example is 'FN' (set of editor files): we receive the main head,
|
|
* with the count of editor files that are sent to us, then we receive one part
|
|
* indicating the size of each files, then for each file, we receive one part,
|
|
* which is the file content.
|
|
*
|
|
* We have one protocol, the CASIOLINK protocol (also called 'legacy protocol'
|
|
* in the libg1m scope), but we have two different type of headers. The two
|
|
* have a fixed width, so they are named by the number of bytes they occupy.
|
|
* Notice that, for what I know, content formats don't vary between header
|
|
* types. The checksuming technique neither. */
|
|
/* ************************************************************************** */
|
|
/* CAS40 header */
|
|
/* ************************************************************************** */
|
|
/* The first header to have appeared is the CAS40 (40 bytes long).
|
|
* It is known in CaS as the protocol the CFX-9700G uses.
|
|
*
|
|
* The header format is the following: */
|
|
|
|
struct cas40 {
|
|
uint8_t data[2]; /* data type -- see `type/cas.c`. */
|
|
uint8_t misc[5]; /* type-specific subheader */
|
|
uint8_t filename[12]; /* editor filename. */
|
|
uint8_t password[12]; /* editor password. */
|
|
uint8_t _reserved[7]; /* 0xFFs */
|
|
uint8_t checksum;
|
|
};
|
|
|
|
/* The specific bytes are different according to the datatype, but its
|
|
* length is fixed. */
|
|
/* ************************************************************************** */
|
|
/* CASDYN header */
|
|
/* ************************************************************************** */
|
|
/* The CASDYN (dynamic size) header appeared later.
|
|
* It is known in CaS as the protocol the CFX-9850G uses.
|
|
*
|
|
* This header format was previously named 'caspro' in libg1m, then CAS50 when
|
|
* I thought the header was always 50 bytes long, then CASDYN as soon as I
|
|
* realized this application system was there on headers of different sizes.
|
|
*
|
|
* I started understanding that this byte between the app and data type I
|
|
* thought was useless was in fact not when I saw in Flash100 sources that it
|
|
* was always 0x31 ('1' in ASCII), which are 40 bytes long. From there and other
|
|
* pieces of documentation, here are the extension types I could find: */
|
|
|
|
# define casdyn_ext_9850 0x00 /* 50 bytes long */
|
|
# define casdyn_ext_end 0xFF /* yet an alias to `casdyn_ext_9850`,
|
|
* used by the END packet. */
|
|
# define casdyn_ext_g100 0x31 /* 40 bytes long */
|
|
# define casdyn_ext_g100b 0x32 /* yet an alias to `casdyn_ext_g100`,
|
|
* used for some commands */
|
|
|
|
/* Here are the common fields to all packets: */
|
|
|
|
struct casdyn {
|
|
/* app */
|
|
uint8_t app[3];
|
|
|
|
/* type of extension - see the `casdyn_ext_*` macros above */
|
|
uint8_t ext;
|
|
};
|
|
|
|
/* The format the CFX-9850G uses is 50 bytes long, so we'll name it CAS50.
|
|
* Here is the header format after the CASDYN header is read: */
|
|
|
|
struct _cas50 {
|
|
/* types */
|
|
uint8_t data[2];
|
|
|
|
/* data length */
|
|
uint16_t width, height;
|
|
uint8_t name[8];
|
|
|
|
/* variable-related data */
|
|
uint8_t prefix[8]; /* "Variable" for vars, 0xFFs otherwise */
|
|
uint8_t aux[8]; /* variable: "R\x0A"/"C\x0A", editor: password */
|
|
|
|
/* something else (?) */
|
|
uint8_t nl[2]; /* 'NL'? */
|
|
uint8_t _reserved[12];
|
|
|
|
/* end of packet */
|
|
uint8_t checksum;
|
|
};
|
|
|
|
/* The format the G100 (AlgebraFX) uses is 40 bytes long, but as CAS40 already
|
|
* exists, we'll name this format CAS100 (which is funny because the Graph 100
|
|
* has a CAS, Computer Algebra System).
|
|
*
|
|
* Information from here is mainly decoded from Flash100 sources.
|
|
* Anyway, here is the CAS100 header after the CASDYN header is read: */
|
|
|
|
struct _cas100 {
|
|
/* drive?
|
|
* - "INF" <1>: system
|
|
* - "FR0" <0>: segment
|
|
* - "MSG" <1>: language
|
|
* - "MR0" <4>: ?
|
|
* - "S00" <0>: ? */
|
|
uint8_t drive[3];
|
|
|
|
/* driver number, in ASCII (0x30 + <num>) */
|
|
uint8_t id;
|
|
|
|
/* group size (size of each fragment group part to be sent): 1024 */
|
|
uint32_t _size;
|
|
|
|
/* ExportDrive: 0x80, type? */
|
|
uint32_t _type;
|
|
|
|
/* drive size: 0x20000 bytes */
|
|
uint32_t drive_size;
|
|
|
|
/* 0xFFs */
|
|
uint8_t _unknown[18];
|
|
|
|
/* checksum */
|
|
uint8_t checksum;
|
|
};
|
|
|
|
/* However, the CAS100 header has a variant, with the 'MDL' application: it
|
|
* looks like system info. The information here is obtained from Flash100's
|
|
* source code, once again. */
|
|
|
|
struct _cas100_info {
|
|
/* board identifier? "ZX945" */
|
|
uint8_t board[5];
|
|
uint8_t _delim0; /* 0xFF */
|
|
|
|
/* serial settings? "038400N"
|
|
* this would mean 38400 bauds, no parity (2 stop bits?) */
|
|
uint8_t settings[11];
|
|
|
|
/* ROM version? "1.00" or "1.01" */
|
|
uint8_t version[4];
|
|
|
|
/* values? */
|
|
uint32_t _val1; /* 0xF00 or 0x1000 */
|
|
uint32_t _val2; /* 0x400 */
|
|
uint32_t _val3; /* 0x100 */
|
|
|
|
/* hex value with prefix... what? */
|
|
uint8_t hex[4]; /* "0x07", litterally, or 0x07 followed by three 0xFFs */
|
|
uint8_t _delim1; /* 0xFF */
|
|
|
|
/* checksum */
|
|
uint8_t checksum;
|
|
};
|
|
|
|
/* As you can guess, CAS40 and CASDYN are, in theory, incompatible.
|
|
* In practice, anyhow, they more or less are: libg1m reads the first 4 bytes
|
|
* from the header, and tries to identify a CASDYN header; if it doesn't manage,
|
|
* it falls back on CAS40.
|
|
*
|
|
* Here are the content formats for the two header types: */
|
|
|
|
# pragma pack()
|
|
# include <libg1m/format/cas/program.h> /* programs, f-mem */
|
|
# include <libg1m/format/cas/cell.h> /* list, matrix, variable */
|
|
# include <libg1m/format/cas/backup.h>
|
|
# include <libg1m/format/cas/picture.h>
|
|
# include <libg1m/format/cas/graph.h>
|
|
# include <libg1m/format/cas/gmem.h>
|
|
#endif /* LIBG1M_FORMAT_CAS_H */
|