diff --git a/src/buttons_effects.c b/src/buttons_effects.c index 7229d3ad..84dc8857 100644 --- a/src/buttons_effects.c +++ b/src/buttons_effects.c @@ -437,6 +437,11 @@ void Button_Constraint_mode(void) Verbose_message("Error!", "Emulation of Amstrad CPC's Mode5 can only be used on an image whose width is a multiple of 48."); return; } + if (Selected_Constraint_Mode == IMAGE_MODE_C64FLI && ((Main.image_width < 160) || (Main.image_height < 200))) + { + Verbose_message("Error!", "Emulation of Commodore 64 FLI Mode needs a 160x200 sized image."); + return; + } // now check the constraints on existing pixels switch (Selected_Constraint_Mode) @@ -467,14 +472,54 @@ void Button_Constraint_mode(void) // switch to layer mode if needed if (Main.backups->Pages->Image_mode != IMAGE_MODE_LAYERED) Switch_layer_mode(IMAGE_MODE_LAYERED); + Main.backups->Pages->Transparent_color = 16; // auto-create extra layers while (Main.backups->Pages->Nb_layers < 3) - if (Add_layer(Main.backups, Main.backups->Pages->Nb_layers)) + if (Add_layer(Main.backups, 0)) { Verbose_message("Error!", "Failed to create the 3 layers needed by C64 Flexible Line Interpretation mode."); return; } - Main.backups->Pages->Transparent_color = 16; + { + word x, y; + byte bitmap[8000],screen_ram[1024*8],color_ram[1024]; + byte background[200]; + + memset(bitmap, 0, sizeof(bitmap)); + memset(screen_ram, 0, sizeof(screen_ram)); + memset(color_ram, 0, sizeof(color_ram)); + memset(background, 0, sizeof(background)); + + // give "hints" to the converter + for (y = 0; y < 200; y++) + background[y] = Read_pixel_from_layer(0, 0, y); + for (y = 0; y < 25; y++) + { + for (x = 0; x < 40; x++) + color_ram[x + y*40] = Read_pixel_from_layer(1, x*4, y*8); + } + + if (C64_pixels_to_FLI(bitmap, screen_ram, color_ram, background, Main.backups->Pages->Image[2].Pixels, Main.image_width, 1) > 0) + { + // put errors in layer 4 if not already done + if (Main.backups->Pages->Nb_layers < 4) + { + Add_layer(Main.backups, Main.backups->Pages->Nb_layers); + C64_pixels_to_FLI(bitmap, screen_ram, color_ram, background, Main.backups->Pages->Image[2].Pixels, Main.image_width, 1); + } + } + + // copy background to layer 1 + // and color RAM to layer 2 + for (y = 0; y < 200; y++) + { + for (x = 0; x < 160; x++) + { + Pixel_in_layer(0, x, y, background[y]); + Pixel_in_layer(1, x, y, color_ram[(x >> 2) + (y >> 3)*40]); + } + } + } break; case IMAGE_MODE_HGR: case IMAGE_MODE_DHGR: diff --git a/src/miscfileformats.c b/src/miscfileformats.c index 1596e533..4036e97e 100644 --- a/src/miscfileformats.c +++ b/src/miscfileformats.c @@ -3348,7 +3348,10 @@ int Save_C64_fli_monolayer(T_IO_Context *context, byte saveWhat, word loadAddr) memset(color_ram, 0, sizeof(color_ram)); memset(background, 0, sizeof(background)); - if (C64_pixels_to_FLI(bitmap, screen_ram, color_ram, background, context->Target_address, context->Pitch) > 0) + memset(color_ram, 0xff, 40*25); // no hint + memset(background, 0xff, 200); + + if (C64_pixels_to_FLI(bitmap, screen_ram, color_ram, background, context->Target_address, context->Pitch, 0) > 0) return 1; file = Open_file_write(context); diff --git a/src/oldies.c b/src/oldies.c index 25021278..340b6009 100644 --- a/src/oldies.c +++ b/src/oldies.c @@ -38,6 +38,7 @@ #include "pages.h" #include "windows.h" #include "layers.h" +#include "graph.h" // I don't have round() in MSVC++ 2010 (_MSC_VER=1600) #if defined(_MSC_VER) @@ -399,7 +400,8 @@ int C64_FLI(T_IO_Context * context, byte *bitmap, byte *screen_ram, byte *color_ } -int C64_pixels_to_FLI(byte *bitmap, byte *screen_ram, byte *color_ram, byte *background, const byte * pixels, long pitch) +int C64_pixels_to_FLI(byte *bitmap, byte *screen_ram, byte *color_ram, + byte *background, const byte * pixels, long pitch, int errmode) { int bx, by; // 4x8 block coordinates int cx, cy; // coordinates inside block @@ -445,13 +447,22 @@ int C64_pixels_to_FLI(byte *bitmap, byte *screen_ram, byte *color_ram, byte *bac if (n_possible_backgrounds == 0) { //ERROR - Warning_with_format("No possible background color for line %d.\n4x1 pixel blocks using 4 different colors must share at least one color.", by*8+cy); - return 1; + if (errmode == 0) + { + Warning_with_format("No possible background color for line %d.\n4x1 pixel blocks using 4 different colors must share at least one color.", by*8+cy); + return 1; + } + error_count++; + GFX2_Log(GFX2_INFO, "C64_pixels_to_FLI() no possible background for line %u. Default to #0.\n", by*8+cy); + // default to background color #0 + if (background[by*8+cy] >= 16) + background[by*8+cy] = 0; } else { - // pick the first one - background[by*8+cy] = count_trailing_zeros(background_possible[cy]); + // if the caller gave us a "hint", check it is "possible" + if (background[by*8+cy] >= 16 || (background_possible[cy] & (1 << background[by*8+cy])) == 0) + background[by*8+cy] = count_trailing_zeros(background_possible[cy]); // pick the first possible #ifdef _DEBUG if (background[by*8+cy] != 0) GFX2_Log(GFX2_DEBUG, " y=%d background_possible=$%04x (count=%d) background color=#%d\n", @@ -488,10 +499,38 @@ int C64_pixels_to_FLI(byte *bitmap, byte *screen_ram, byte *color_ram, byte *bac // choose the color RAM values (default to #0) if (color_ram_possible[bx] == 0) { - Warning_with_format("No possible color RAM value for 4x8 block (%d,%d) coordinates (%d,%d)\nThe 8 4x1 blocks must share a color.", bx, by, bx*4, by*8); - return 1; + if (errmode == 0) + { + Warning_with_format("No possible color RAM value for 4x8 block (%d,%d) coordinates (%d,%d)\nThe 8 4x1 blocks must share a color.", bx, by, bx*4, by*8); + return 1; + } + else + { + // Mark errors in Layer 4 + for(cy = 0; cy < 8; cy++) + { + word colors_used = 0; + for(cx = 0; cx < 4; cx++) + { + pixel = pixels[bx*4+cx + pitch*(by*8+cy)]; + if (pixel < 16 && pixel != background[by*8+cy]) + colors_used |= 1 << pixel; + } + if (count_set_bits(colors_used) >= 3) + { + error_count++; + GFX2_Log(GFX2_INFO, "C64_pixels_to_FLI() too much colors in block at (%u to %u, %u)\n", bx*4, bx*4+3, by*7+cy); + for(cx = 0; cx < 4; cx++) + { + pixel = pixels[bx*4+cx + pitch*(by*8+cy)]; + if (pixel < 16 && pixel != background[by*8+cy] && Main.backups->Pages->Nb_layers >= 4) + Pixel_in_layer(3, bx*4+cx, by*8+cy, 17); + } + } + } + } } - else + else if (color_ram[by*40+bx] >= 16 || ((1 << color_ram[by*40+bx]) & color_ram_possible[bx]) == 0) { word possible = color_ram_possible[bx]; // avoid using same color as background diff --git a/src/oldies.h b/src/oldies.h index c4f9d46c..26f444f3 100644 --- a/src/oldies.h +++ b/src/oldies.h @@ -43,15 +43,22 @@ int C64_FLI(T_IO_Context * context, byte *bitmap, byte *screen_ram, byte *color_ /** * Convert a (1 layer) picture to C64 FLI format * + * Some "hints" can be put in background and color_ram. + * (a color value >= 16 means no hint). + * + * Errors can be either outputed to the user with Warning messages, + * or put in layer 4. The layer 4 has to be created before. + * * @param bitmap a 8000 byte buffer to store bitmap data * @param screen_ram a 8192 byte buffer to store the 8 screen RAMs * @param color_ram a 1000 byte buffer to store the color RAM * @param background a 200 byte buffer to store the background colors * @param pixels source pixel buffer (at least 160x200) * @param pitch bytes per line of the pixel buffer + * @param errmode error reporting mode 0 = report, 1 = mark in layer 4 * @return 0 the number of constraint errors */ -int C64_pixels_to_FLI(byte *bitmap, byte *screen_ram, byte *color_ram, byte *background, const byte * pixels, long pitch); +int C64_pixels_to_FLI(byte *bitmap, byte *screen_ram, byte *color_ram, byte *background, const byte * pixels, long pitch, int errmode); #if 0 /**