193 lines
6.8 KiB
C
193 lines
6.8 KiB
C
|
/* *****************************************************************************
|
||
|
* 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. */
|
||
|
/* ************************************************************************** */
|
||
|
/* 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 */
|