From 77262deadc34ab47c782e83f3e921ba143c9d310 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 12 Nov 2018 02:03:31 +0100 Subject: [PATCH] Add Loading of files produced by TGA2TEO for the Thomson TO8 --- src/const.h | 1 + src/fileformats.h | 4 + src/loadsave.c | 3 +- src/miscfileformats.c | 198 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 205 insertions(+), 1 deletion(-) diff --git a/src/const.h b/src/const.h index a7936ac8..7984fa95 100644 --- a/src/const.h +++ b/src/const.h @@ -147,6 +147,7 @@ enum FILE_FORMATS FORMAT_ICO, ///< Windows icons FORMAT_INFO, ///< Amiga OS icons FORMAT_FLI, ///< Autodesk Animator FLI/FLC + FORMAT_MOTO, ///< Thomson MO/TO computers pictures FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image }; diff --git a/src/fileformats.h b/src/fileformats.h index a2766d6a..13db5727 100644 --- a/src/fileformats.h +++ b/src/fileformats.h @@ -141,4 +141,8 @@ void Load_INFO(T_IO_Context *); void Test_FLI(T_IO_Context *, FILE *); void Load_FLI(T_IO_Context *); +// -- Thomson MO/TO computer series pictures -------------------------------- +void Test_MOTO(T_IO_Context *, FILE *); +void Load_MOTO(T_IO_Context *); + #endif diff --git a/src/loadsave.c b/src/loadsave.c index 0bb93712..fef8f45f 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -90,7 +90,7 @@ const T_Format File_formats[] = { {FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "", "gif;png;bmp;2bp;pcx;pkm;iff;lbm;ilbm;sham;ham;ham6;ham8;acbm;pic;anim;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;" "c64;p64;a64;pi;rp;aas;art;dd;iph;ipt;hpc;ocp;koa;koala;fli;" - "bml;cdu;prg;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;ic2;cur;cm5;pph;info;flc"}, + "bml;cdu;prg;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;ic2;cur;cm5;pph;info;flc;bin"}, {FORMAT_ALL_PALETTES, "(pal)", NULL, NULL, NULL, 1, 0, 0, "", "kcf;pal;gpl"}, {FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"}, {FORMAT_GIF, " gif", Test_GIF, Load_GIF, Save_GIF, 0, 1, 1, "gif", "gif"}, @@ -120,6 +120,7 @@ const T_Format File_formats[] = { {FORMAT_ICO, " ico", Test_ICO, Load_ICO, Save_ICO, 0, 0, 0, "ico", "ico;ic2;cur"}, {FORMAT_INFO," info",Test_INFO,Load_INFO,NULL, 0, 0, 0, "info", "info"}, {FORMAT_FLI, " flc", Test_FLI, Load_FLI, NULL, 0, 0, 0, "flc", "flc;fli;dat"}, + {FORMAT_MOTO," moto",Test_MOTO,Load_MOTO,NULL, 0, 0, 0, "bin", "bin"}, {FORMAT_MISC,"misc.",NULL, NULL, NULL, 0, 0, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff"}, }; diff --git a/src/miscfileformats.c b/src/miscfileformats.c index d0d01a00..d515d09f 100644 --- a/src/miscfileformats.c +++ b/src/miscfileformats.c @@ -4858,3 +4858,201 @@ void Load_FLI(T_IO_Context * context) } fclose(file); } + +/////////////////////////////// Thomson Files /////////////////////////////// + +/** + * Test for Thomson file + */ +void Test_MOTO(T_IO_Context * context, FILE * file) +{ + long file_size; + + (void)context; + file_size = File_length_file(file); + + switch (file_size) + { + case 8004: // 2 colors palette + case 8008: // 4 colors palette + case 8032: // 16 colors palette + File_error = 0; + break; + default: + File_error = 1; + } +} + +/** + * Load a picture for Thomson TO8/TO8D/TO9/TO9+/MO6 + * + * The format used is the one produced by TGA2Teo : + * - Picture data is splitted into 2 files, one for each VRAM bank : + * - The first VRAM bank is called "forme" (shape). + * In 40col mode it stores pixels. + * - The second VRAM bank is called "couleur" (color). + * In 40col mode it store color indexes for foreground and background. + * - File extension is .BIN, character before extension is "P" for the first + * file, and "C" for the second. + * - The color palette is stored in both files after the data. + * + * The mode is detected thanks to the number of color in the palette : + * - 2 colors is 80col (640x200) + * - 4 colors is bitmap4 (320x200 4 colors) + * - 16 colors is either bitmap16 (160x200 16colors) + * or 40col (320x200 16 colors with 2 unique colors in each 8x1 pixels + * block). + * + * As it is not possible to disriminate bitmap16 and 40col, opening the "P" + * file sets bitmap16, opening the "C" file sets 40col. + */ +void Load_MOTO(T_IO_Context * context) +{ + // FORME / COULEUR + FILE * file_forme; + FILE * file_couleur = NULL; + long file_size; + int n_colors; + int bx, x, y; + char filename[MAX_PATH_CHARACTERS]; + char path[MAX_PATH_CHARACTERS]; + byte bpp; + char * ext; + enum MOTO_mode { F_40col, F_80col, F_bm4, F_bm16 } mode = F_40col; + enum PIXEL_RATIO ratio = PIXEL_SIMPLE; + int width = 320; + static const int gamma[16] = { // Gamma values for MO6/TO8 palette + 0 , 100, 127, 147, + 163, 179, 191, 203, + 215, 223, 231, 239, + 243, 247, 251, 255 + }; + + + File_error = 1; + file_forme = Open_file_read(context); + if (file_forme == NULL) + return; + file_size = File_length_file(file_forme); + n_colors = (file_size - 8000) / 2; + switch(n_colors) + { + case 16: + bpp = 4; + // 16 colors : either 40col or bm16 mode ! + // select later + break; + case 4: + bpp = 2; + mode = F_bm4; + break; + default: + bpp = 1; + mode = F_80col; + width = 640; + ratio = PIXEL_TALL; + } + strncpy(filename, context->File_name, sizeof(filename)); + filename[sizeof(filename)-1] = '\0'; + ext = strrchr(filename, '.'); + if (ext == NULL || ext == context->File_name) + { + fclose(file_forme); + return; + } + if ((ext[-1] | 32) == 'c') + { + file_couleur = file_forme; + ext[-1] = (ext[-1] & 32) | 'P'; + Get_full_filename(path, filename, context->File_directory); + file_forme = fopen(path, "rb"); + } + else if ((ext[-1] | 32) == 'p') + { + ext[-1] = (ext[-1] & 32) | 'C'; + Get_full_filename(path, filename, context->File_directory); + file_couleur = fopen(path, "rb"); + if (n_colors == 16) + { + mode = F_bm16; + width = 160; + ratio = PIXEL_WIDE; + } + } + if (file_couleur == NULL) + { + fclose(file_forme); + return; + } + GFX2_Log(GFX2_DEBUG, "MO/TO: %s,%s file_size=%ld n_colors=%d\n", context->File_name, filename, file_size, n_colors); + Pre_load(context, width, 200, file_size, FORMAT_MOTO, ratio, bpp); + File_error = 0; + for (y = 0; y < 200; y++) + { + for (bx = 0; bx < 40; bx++) + { + byte couleur_forme; + byte couleur_fond; + byte forme, couleurs; + + if (!(Read_byte(file_forme,&forme) && Read_byte(file_couleur,&couleurs))) + File_error = 1; + switch(mode) + { + case F_bm4: + for (x = bx*8; x < bx*8+8; x++) + { + Set_pixel(context, x, y, ((forme & 0x80) >> 6) | ((couleurs & 0x80) >> 7)); + forme <<= 1; + couleurs <<= 1; + } +#if 0 + for (x = bx*8; x < bx*8+4; x++) + { + Set_pixel(context, x, y, couleurs >> 6); + couleurs <<= 2; + } + for (x = bx*8 + 4; x < bx*8+8; x++) + { + Set_pixel(context, x, y, forme >> 6); + forme <<= 2; + } +#endif + break; + case F_bm16: + Set_pixel(context, bx*4, y, forme >> 4); + Set_pixel(context, bx*4+1, y, forme & 0x0F); + Set_pixel(context, bx*4+2, y, couleurs >> 4); + Set_pixel(context, bx*4+3, y, couleurs & 0x0F); + break; + case F_40col: + default: + // the color plane byte is bfFFFBBB + // with the upper bits of both foreground (forme) and + // background (fond) inverted. + couleur_forme = ((couleurs & 0x78) >> 3) ^ 0x08; + couleur_fond = ((couleurs & 7) | ((couleurs & 0x80) >> 4)) ^ 0x08; + for (x = bx*8; x < bx*8+8; x++) + { + Set_pixel(context, x, y, (forme & 0x80)?couleur_forme:couleur_fond); + forme <<= 1; + } + } + } + } + for (x = 0; x < n_colors; x++) + { + byte value; + // 1 byte Blue (4 lower bits) + // 1 byte Green (4 upper bits) / Red (4 lower bits) + if (!Read_byte(file_forme,&value)) + File_error = 1; + context->Palette[x].B = gamma[value & 0x0F]; + if (!Read_byte(file_forme,&value)) + File_error = 1; + context->Palette[x].G = gamma[value >> 4]; + context->Palette[x].R = gamma[value & 0x0F]; + } + fclose(file_forme); + fclose(file_couleur); +}