diff --git a/include/libg1m/picture.h b/include/libg1m/picture.h index 0694804..101ae8c 100644 --- a/include/libg1m/picture.h +++ b/include/libg1m/picture.h @@ -18,50 +18,148 @@ * ************************************************************************** */ #ifndef LIBG1M_PICTURE_H # define LIBG1M_PICTURE_H +# include +/* This file describes the picture formats CASIO has used for various purposes + * (screenshots, pictures, screenstreaming), and that libg1m is able to + * decode. + * + * The formats pictures should fit in a `g1m_pictureformat_t`. + * They are more or less organized as 0xBBVS, where BB is the number of bits + * each pixel occupy (in total), V is the variation for this number of bits, + * and S is the special hex digit (e.g. reverse). */ + +typedef unsigned int g1m_pictureformat_t; /* ************************************************************************** */ -/* Picture formats */ +/* Monochrome pictures with fill bits */ /* ************************************************************************** */ -/* picture format */ -typedef int g1m_pictureformat_t; +/* In this format, each bit represents a pixel (so one byte contains eight + * pixels). If the width is not divisible by eight, then the last bits of the + * last byte of the line are unused (fill bits), and the next line starts at + * the beginning of the next byte ; this makes the navigation between lines + * easier, but takes up more space. + * + * An off bit (0b0) represents a white pixel, and an on bit (0b1) represents + * a black pixel. Reverse white and black in the `_r` special type. */ + # define g1m_pictureformat_1bit 0x0100 # define g1m_pictureformat_1bit_r 0x0101 -# define g1m_pictureformat_1bit_packed 0x0110 -# define g1m_pictureformat_1bit_packed_r 0x0111 -# define g1m_pictureformat_1bit_packed_old 0x0120 -# define g1m_pictureformat_2bit_dual 0x0200 -# define g1m_pictureformat_4bit_rgb 0x0400 -# define g1m_pictureformat_4bit_code 0x0410 -# define g1m_pictureformat_4bit_color 0x0420 -# define g1m_pictureformat_4bit_mono 0x0430 -# define g1m_pictureformat_16bit 0x1000 -/* ************************************************************************** */ -/* Picture sizes */ -/* ************************************************************************** */ +/* To calculate the size, it's simple: just calculate the number of bytes + * a line occupies, then multiply it by the number of lines. */ + # define g1m_picturesize_1bit(W, H) \ ((((W) / 8) + !!((W) % 8)) * (H)) -# define g1m_picturesize_1bit_packed(W, H) \ - ((W) * (H) / 8) -# define g1m_picturesize_1bit_packed_r(W, H) \ - g1m_picturesize_1bit_packed(W, H) -# define g1m_picturesize_1bit_packed_old(W, H) \ - g1m_picturesize_1bit_packed(W, H) +# define g1m_picturesize_1bit_r(W, H) \ + g1m_picturesize_1bit((W), (H)) +/* ************************************************************************** */ +/* Packed monochrome pictures */ +/* ************************************************************************** */ +/* Packed monochrome pictures is basically the same than the previous format, + * except there are no fill bits: if a picture width is 6 pixels, then the + * second line will start at the seventh bit of the first byte (where it would + * start at the first bit of the second byte with fill bits). + * + * The navigation to a line is less easy as it takes at least one division. */ -# define g1m_picturesize_4bit_color(W, H) \ - (4 * g1m_picturesize_1bit_packed_old(W, H)) -# define g1m_picturesize_4bit_mono(W, H) \ - g1m_picturesize_4bit_color(W, H) +# define g1m_pictureformat_1bit_packed 0x0110 +# define g1m_pictureformat_1bit_packed_r 0x0111 + +/* To calculate the size, find out the number of occupied bits, divide by + * eight to get the bytes, and make sure to keep an extra byte if there are + * left bits. */ + +# define g1m_picturesize_1bit_packed(W, H) \ + (((W) * (H) / 8) + !!((W) * (H) % 8)) +/* ************************************************************************** */ +/* Old monochrome format */ +/* ************************************************************************** */ +/* The old monochrome format used by CASIO is basically a normal monochrome + * format (the width is usually 96 or 128, so no need for fill bits), except + * that it starts with the last byte (where the bits are in left to right + * order), but then it goes from right to left, and from bottom to top. */ + +# define g1m_pictureformat_1bit_old 0x0120 + +/* The size is the same as for normal 1-bit monochrome pictures, only the + * byte order changes. */ + +# define g1m_picturesize_1bit_old(W, H) \ + g1m_picturesize_1bit(W, H) +/* ************************************************************************** */ +/* Dual monochrome format */ +/* ************************************************************************** */ +/* This is the format used for the Prizm's projector mode. It is composed of + * two monochrome pictures (with sizes divisible by eight). + * It is basically gray pictures, with white, light gray, dark gray and + * black. */ + +# define g1m_pictureformat_2bit_dual 0x0200 + +/* To calculate the size, well, we just have two monochrome screens. */ # define g1m_picturesize_2bit_dual(W, H) \ - (((W) * (H) / 4) * 2) + (g1m_picturesize_1bit(W, H) * 2) +/* ************************************************************************** */ +/* 4-bit RGB_ format */ +/* ************************************************************************** */ +/* This is a 4 bit per pixel format. There is no need for fill bits (?). + * Each nibble (group of 4 bits) is made of the following: + * - one bit for red (OR by 0xFF0000); + * - one bit for green (OR by 0x00FF00); + * - one bit for blue (OR by 0x0000FF); + * - one alignment bit. */ + +# define g1m_pictureformat_4bit 0x0400 +# define g1m_pictureformat_4bit_rgb 0x0400 + +/* Calculating the size is trivial. */ + # define g1m_picturesize_4bit(W, H) \ ((W) * (H) / 2) - # define g1m_picturesize_4bit_rgb(W, H) \ g1m_picturesize_4bit(W, H) +/* ************************************************************************** */ +/* 4-bit code format */ +/* ************************************************************************** */ +/* In this encoding, each nibble for a pixel represents one of the color codes + * defined in `libg1m/color.h`. */ + +# define g1m_pictureformat_4bit_code 0x0410 + +/* The size is calculated the same way as previously. */ + # define g1m_picturesize_4bit_code(W, H) \ g1m_picturesize_4bit(W, H) +/* ************************************************************************** */ +/* Quad-monochrome VRAM formats */ +/* ************************************************************************** */ +/* This format is used by old CASIO models. It is made of four monochrome + * pictures (no need for fill bits), where the palettes are: + * - for the `color` variant: [orange, green, blue, white (bg)] + * - for the `mono` variant: [(unused), (unused), black, white (bg)] */ + +# define g1m_pictureformat_4bit_color 0x0420 +# define g1m_pictureformat_4bit_mono 0x0421 + +/* Just multiply the size of a VRAM by four. */ + +# define g1m_picturesize_4bit_color(W, H) \ + (4 * g1m_picturesize_1bit_old(W, H)) +# define g1m_picturesize_4bit_mono(W, H) \ + g1m_picturesize_4bit_color(W, H) +/* ************************************************************************** */ +/* 16-bit R5G6B5 format */ +/* ************************************************************************** */ +/* This is the format of the Prizm's VRAM. Each pixel is two bytes long, + * the first five bits represent the high five (clap!) bits of the red part, + * the next six bits represent the high six bits of the green part, + * the last five bits represent the high five (re-clap!) bits of the blue + * part. */ + +# define g1m_pictureformat_16bit 0x1000 + +/* Two bytes per pixel. */ # define g1m_picturesize_16bit(W, H) \ ((W) * (H) * 2) diff --git a/src/utils/picture.c b/src/utils/picture.c index b4b4e4f..6997fab 100644 --- a/src/utils/picture.c +++ b/src/utils/picture.c @@ -116,7 +116,7 @@ int g1m_decode_picture(uint32_t **pixels, g1m_pictureformat_t format, } break; - case g1m_pictureformat_1bit_packed_old: + case g1m_pictureformat_1bit_old: for (unsigned int bx = width - 8; bx != (unsigned int)-8; bx -= 8) for (unsigned int y = height - 1; y != (unsigned int)-1; y--) { msk = 0x80;