/* ***************************************************************************** * libg1m/format/casemul.h -- the Casemul file format description. * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey * * 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 . * ************************************************************************** */ #ifndef LIBG1M_FORMAT_CASEMUL_H # define LIBG1M_FORMAT_CASEMUL_H # include # 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; }; /* Then it's simply a tab of `lines*columns` `double` numbers, * ordered by lines (y). They are the real parts, as the numbers in those * matrixes have got no imaginary parts. */ /* ************************************************************************** */ /* 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; }; /* Then it's simply a tab of `lines` `double` numbers. * The numbers in these have no imaginary parts. */ # pragma pack() #endif /* LIBG1M_FORMAT_CASEMUL_H */