diff --git a/src/const.h b/src/const.h index efec8a4d..6c7903ae 100644 --- a/src/const.h +++ b/src/const.h @@ -148,6 +148,7 @@ enum FILE_FORMATS FORMAT_INFO, ///< Amiga OS icons FORMAT_FLI, ///< Autodesk Animator FLI/FLC FORMAT_MOTO, ///< Thomson MO/TO computers pictures + FORMAT_HGR, ///< Apple II HGR and DHGR FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image }; diff --git a/src/fileformats.h b/src/fileformats.h index 3bbe4f1d..48298ec1 100644 --- a/src/fileformats.h +++ b/src/fileformats.h @@ -155,5 +155,10 @@ void Test_MOTO(T_IO_Context *, FILE *); void Load_MOTO(T_IO_Context *); void Save_MOTO(T_IO_Context *); +// -- Apple II HGR and DHGR pictures ---------------------------------------- +void Test_HGR(T_IO_Context *, FILE *); +void Load_HGR(T_IO_Context *); +void Save_HGR(T_IO_Context *); + /// @} #endif diff --git a/src/loadsave.c b/src/loadsave.c index 4dbf3de3..9f2decf0 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -91,6 +91,7 @@ const T_Format File_formats[] = { "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;pmg;rpm;" "cpc;scr;win;" + "hgr;dhgr;" "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;ic2;cur;cm5;pph;info;flc;bin;map"}, {FORMAT_ALL_PALETTES, "(pal)", NULL, NULL, NULL, 1, 0, 0, "", "kcf;pal;gpl"}, {FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"}, @@ -123,6 +124,7 @@ const T_Format File_formats[] = { {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,Save_MOTO,0, 1, 0, "bin", "bin;map"}, + {FORMAT_HGR, " hgr", Test_HGR, Load_HGR, Save_HGR, 0, 0, 1, "hgr", "hgr;dhgr;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 4af42e8a..58613bb0 100644 --- a/src/miscfileformats.c +++ b/src/miscfileformats.c @@ -6671,3 +6671,240 @@ error: fclose(file); File_error = 1; } + +/////////////////////////////// Apple II Files ////////////////////////////// + +/** + * Test for an Apple II HGR or DHGR raw file + */ +void Test_HGR(T_IO_Context * context, FILE * file) +{ + long file_size; + + (void)context; + File_error = 1; + + file_size = File_length_file(file); + if (file_size == 8192) // HGR + File_error = 0; + else if(file_size == 16384) // DHGR + File_error = 0; +} + +/** + * Load HGR (280x192) or DHGR (560x192) Apple II pictures + * + * Creates 2 layers : + * 1. Monochrome + * 2. Color + */ +void Load_HGR(T_IO_Context * context) +{ + unsigned long file_size; + FILE * file; + byte * vram[2]; + int bank; + int x, y; + int is_dhgr = 0; + + file = Open_file_read(context); + if (file == NULL) + { + File_error = 1; + return; + } + file_size = File_length_file(file); + if (file_size == 16384) + is_dhgr = 1; + + vram[0] = malloc(8192); + Read_bytes(file, vram[0], 8192); + if (is_dhgr) + { + vram[1] = malloc(8192); + Read_bytes(file, vram[1], 8192); + } + else + vram[1] = NULL; + fclose(file); + + if (Config.Clear_palette) + memset(context->Palette,0,sizeof(T_Palette)); + if (is_dhgr) + { + DHGR_set_palette(context->Palette); + Pre_load(context, 560, 192, file_size, FORMAT_HGR, PIXEL_TALL, 4); + } + else + { + HGR_set_palette(context->Palette); + Pre_load(context, 280, 192, file_size, FORMAT_HGR, PIXEL_SIMPLE, 2); + } + for (y = 0; y < 192; y++) + { + byte palette = 0, color = 0; + byte previous_palette = 0; // palette for the previous pixel pair + int column, i; + int offset = ((y & 7) << 10) + ((y & 070) << 4) + ((y >> 6) * 40); + x = 0; + for (column = 0; column < 40; column++) + for (bank = 0; bank <= is_dhgr; bank++) + { + byte b = vram[bank][offset+column]; + if (!is_dhgr) + palette = (b & 0x80) ? 4 : 0; + else + palette = (b & 0x80) ? 0 : 16; + for (i = 0; i < 7; i++) + { + if (context->Type == CONTEXT_MAIN_IMAGE) + { + // monochrome + Set_loading_layer(context, 0); + Set_pixel(context, x, y, ((b & 1) * (is_dhgr ? 15 : 3)) + palette); + Set_loading_layer(context, 1); + } + // color + color = (color << 1) | (b & 1); + if (is_dhgr) + { + if ((x & 3) == 0) + previous_palette = palette; // what is important is the value when the 1st bit was read... + /// emulate "chat mauve" DHGR mixed mode. + /// see http://boutillon.free.fr/Underground/Anim_Et_Graph/Extasie_Chat_Mauve_Reloaded/Extasie_Chat_Mauve_Reloaded.html + if (previous_palette) // BW + Set_pixel(context, x, y, ((b & 1) * 15) + palette); + else if ((x & 3) == 3) + { + Set_pixel(context, x - 3, y, (color & 15) + palette); + Set_pixel(context, x - 2, y, (color & 15) + palette); + Set_pixel(context, x - 1, y, (color & 15) + palette); + Set_pixel(context, x, y, (color & 15) + palette); + } + } + else + { + if (x & 1) + { + if ((color & 6) == 6) // 2 bits to 1 => force White + { + Set_pixel(context, x - 2, y, 3 + previous_palette); + Set_pixel(context, x - 1, y, 3 + palette); + } + else + Set_pixel(context, x - 1, y, (color & 3) + palette); + Set_pixel(context, x, y, (color & 3) + palette); + previous_palette = palette; + } + } + b >>= 1; + x++; + } + } + } + // show hidden data in HOLES + for (y = 0; y < 64; y++) + for (bank = 0; bank < 1; bank++) + { + byte b = 0; + for (x = 0; x < 8; x++) + b |= vram[bank][x + (y << 7) + 120]; + if (b != 0) + GFX2_LogHexDump(GFX2_DEBUG, bank ? "AUX " : "MAIN", vram[bank], (y << 7) + 120, 8); + } + free(vram[0]); + free(vram[1]); + File_error = 0; +} + +/** + * Save HGR (280x192) or DHGR (560x192) Apple II pictures + * + * The data saved is the "monochrome" data from layer 1 + */ +void Save_HGR(T_IO_Context * context) +{ + FILE * file; + byte * vram[2]; + int bank; + int x, y; + int is_dhgr = 0; + + File_error = 1; + if (context->Height != 192 || (context->Width != 280 && context->Width != 560)) + { + Warning_message("Picture must be 280x192 (HGR) or 560x192 (DHGR)"); + return; + } + if (context->Width == 560) + is_dhgr = 1; + + file = Open_file_write(context); + if (file == NULL) + return; + vram[0] = calloc(8192, 1); + if (vram[0] == NULL) + { + fclose(file); + return; + } + if (is_dhgr) + { + vram[1] = calloc(8192, 1); + if (vram[1] == NULL) + { + free(vram[0]); + fclose(file); + return; + } + } + else + vram[1] = NULL; + + Set_saving_layer(context, 0); // "monochrome" layer + for (y = 0; y < 192; y++) + { + int i, column = 0; + int offset = ((y & 7) << 10) + ((y & 070) << 4) + ((y >> 6) * 40); + x = 0; + bank = 0; + while (x < context->Width) + { + byte b; + if (is_dhgr) + b = (Get_pixel(context, x, y) & 16) ? 0 : 0x80; + else + b = (Get_pixel(context, x, y) & 4) ? 0x80 : 0; + for (i = 0; i < 7; i++) + { + b = b | ((Get_pixel(context, x++, y) & 1) << i); + } + vram[bank][offset + column] = b; + if (is_dhgr) + { + if (++bank > 1) + { + bank = 0; + column++; + } + } + else + column++; + } + } + + if (Write_bytes(file, vram[0], 8192)) + { + if (is_dhgr) + { + if (Write_bytes(file, vram[1], 8192)) + File_error = 0; + } + else + File_error = 0; + } + + free(vram[0]); + free(vram[1]); + fclose(file); +} diff --git a/src/oldies.c b/src/oldies.c index 8997f639..a685b2f1 100644 --- a/src/oldies.c +++ b/src/oldies.c @@ -2,6 +2,7 @@ */ /* Grafx2 - The Ultimate 256-color bitmap paint program + Copyright 2018 Thomas Bernard Copyright 2008 Yves Rizoud Copyright 2008 Franck Charlet Copyright 2007 Adrien Destugues @@ -748,3 +749,48 @@ void MOTO_set_TO7_palette(T_Components * palette) palette[17].G = 127; palette[17].B = 127; } + +void HGR_set_palette(T_Components * palette) +{ + static const T_Components hgr_palette[] = { + { 0, 0, 0 }, // black + { 0, 255, 0 }, // green + { 255, 0, 255 }, // purple + { 255, 255, 255 }, // white + { 0, 0, 0 }, // black + { 255, 80, 0 }, // orange + { 0, 175, 255 }, // blue + { 255, 255, 255 } // white + }; + memcpy(palette, hgr_palette, sizeof(hgr_palette)); +} + +void DHGR_set_palette(T_Components * palette) +{ + // Color Palette from the JACE emulator + static const T_Components dhgr_palette[] = { + {0,0,0}, /* 0 black */ + {177,0,93}, /* 1 red */ + {94,86,0}, /* 8 brown */ + {255,86,0}, /* 9 orange */ + {0,127,34}, /* 4 dk green */ + {127,127,127},/* 5 gray */ + {44,213,0}, /* 12 lt green */ + {222,213,0}, /* 13 yellow */ + {32,41,255}, /* 2 dk blue */ + {210,41,255}, /* 3 purple */ + {127,127,127},/* 10 grey */ + {255,127,220},/* 11 pink */ + {0,168,255}, /* 6 med blue */ + {160,168,255},/* 7 lt blue */ + {77,255,161}, /* 14 aqua */ + {255,255,255} /* 15 white */ + }; + memcpy(palette, dhgr_palette, sizeof(dhgr_palette)); + palette[16].R = 0; + palette[16].G = 0; + palette[16].B = 0; + palette[31].R = 255; + palette[31].G = 255; + palette[31].B = 255; +} diff --git a/src/oldies.h b/src/oldies.h index 7abce6fd..d6a498c8 100644 --- a/src/oldies.h +++ b/src/oldies.h @@ -2,6 +2,7 @@ */ /* Grafx2 - The Ultimate 256-color bitmap paint program + Copyright 2018 Thomas Bernard Copyright 2008 Adrien Destugues Grafx2 is free software; you can redistribute it and/or @@ -224,3 +225,21 @@ void MOTO_set_MO5_palette(T_Components * palette); void MOTO_set_TO7_palette(T_Components * palette); /** @}*/ + +/** @defgroup apple2 Apple II + * + * HGR and DHGR modes + * @{ + */ + +/** + * Set the 6 color Apple II HGR palette + */ +void HGR_set_palette(T_Components * palette); + +/** + * Set the 16 color Apple II DHGR palette + */ +void DHGR_set_palette(T_Components * palette); + +/** @}*/