From f003bd86787bbf89feb1d44772020008fad6c94a Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Sun, 9 Dec 2018 02:21:12 +0100 Subject: [PATCH] Add C64 FLI drawing mode todo : conversions from flat images --- src/brush.c | 28 +++++++++++-- src/buttons_effects.c | 15 ++++++- src/graph.c | 91 ++++++++++++++++++++++++++++++++++++++++++- src/helpfile.h | 10 +++++ 4 files changed, 138 insertions(+), 6 deletions(-) diff --git a/src/brush.c b/src/brush.c index a5e88df9..26520cf8 100644 --- a/src/brush.c +++ b/src/brush.c @@ -122,9 +122,9 @@ void Display_paintbrush(short x,short y,byte color) if ((Main.backups->Pages->Image_mode == IMAGE_MODE_MODE5 || Main.backups->Pages->Image_mode == IMAGE_MODE_RASTER) && Main.current_layer < 4) - { goto single_pixel; - } + if ((Main.backups->Pages->Image_mode == IMAGE_MODE_C64FLI) && Main.current_layer < 2) + goto single_pixel; switch (Paintbrush_shape) { case PAINTBRUSH_SHAPE_NONE : // No paintbrush. for colorpicker for example @@ -285,8 +285,9 @@ void Draw_paintbrush(short x,short y,byte color) int position; byte old_color; - if ((Main.backups->Pages->Image_mode == IMAGE_MODE_MODE5 + if (((Main.backups->Pages->Image_mode == IMAGE_MODE_MODE5 || Main.backups->Pages->Image_mode == IMAGE_MODE_RASTER) && Main.current_layer < 4) + || (Main.backups->Pages->Image_mode == IMAGE_MODE_C64FLI && Main.current_layer < 2)) { // Flood-fill the enclosing area if (x= 0 && y >= 0 @@ -327,7 +328,26 @@ void Draw_paintbrush(short x,short y,byte color) height=1; break; } - } else { + } + else if (Main.backups->Pages->Image_mode == IMAGE_MODE_C64FLI) + { + if (Main.current_layer == 0) // background + { // full line + min_x=0; + min_y=y; + width=Main.image_width; + height=1; + } + else // Color RAM + { // 4x8 Block + min_x=x&~3; + min_y=y&~7; + width=4; + height=8; + } + } + else + { int prev_x; // Raster mode IMAGE_MODE_RASTER // No matter what, you can always edit only 1 line at a time here, and you will always diff --git a/src/buttons_effects.c b/src/buttons_effects.c index 77aac882..7229d3ad 100644 --- a/src/buttons_effects.c +++ b/src/buttons_effects.c @@ -463,6 +463,19 @@ void Button_Constraint_mode(void) } } break; + case IMAGE_MODE_C64FLI: + // switch to layer mode if needed + if (Main.backups->Pages->Image_mode != IMAGE_MODE_LAYERED) + Switch_layer_mode(IMAGE_MODE_LAYERED); + // auto-create extra layers + while (Main.backups->Pages->Nb_layers < 3) + if (Add_layer(Main.backups, Main.backups->Pages->Nb_layers)) + { + Verbose_message("Error!", "Failed to create the 3 layers needed by C64 Flexible Line Interpretation mode."); + return; + } + Main.backups->Pages->Transparent_color = 16; + break; case IMAGE_MODE_HGR: case IMAGE_MODE_DHGR: // switch to layer mode if needed @@ -515,7 +528,7 @@ void Button_Constraint_menu(void) {IMAGE_MODE_RASTER, "Rasters (CPC)", "CPC Rasters ", 1}, {IMAGE_MODE_C64HIRES,"C64 HiRes", "2 colors per 8x8 block", 1}, // 320x200 {IMAGE_MODE_C64MULTI,"C64 Multicolor","4 colors per 4x1 block", 1}, // 160x200 - //{IMAGE_MODE_C64FLI, "C64 FLI", "improved multicolor ", 1}, // 160x200 + {IMAGE_MODE_C64FLI, "C64 FLI", "improved multicolor ", 1}, // 160x200 {IMAGE_MODE_HGR, "Apple II HGR", "6 colors ", 1}, // 280x192 {IMAGE_MODE_DHGR, "Apple II DHGR", "\"Le Chat Mauve\" mode3 ", 1}, // 560x192 }; diff --git a/src/graph.c b/src/graph.c index ee350c4b..419fa786 100644 --- a/src/graph.c +++ b/src/graph.c @@ -3505,6 +3505,88 @@ static void Pixel_in_screen_c64multi_with_opt_preview(word x,word y,byte color,i } } + +/// Paint in the background or Color RAM layer of C64 FLI +/// +/// Update the bitmap layer pixel if needed +static void Pixel_in_screen_c64fli_underlay_with_opt_preview(word x,word y,byte color,int preview) +{ + byte oldcolor = Read_pixel_from_current_layer(x, y); + + // does it changes the upper layer (3) ? + if (oldcolor != Read_pixel_from_layer(Main.current_layer ^ 1, x, y) + && oldcolor == Read_pixel_from_layer(2, x, y)) + { + Pixel_in_layer(2, x, y, color); + if (((1 << 2) & Main.layers_visible) != 0 + && (Main_visible_image_depth_buffer.Image[+x+y*Main.image_width] <= 2)) + { + Main_screen[x+y*Main.image_width]=color; + if (preview) + Pixel_preview(x,y,color); + } + } + + Pixel_in_screen_layered_with_opt_preview(x, y, color, preview); +} + +/// Paint in the bitmap layer of C64 FLI +/// +/// enforce C64 FLI mode constraints. +static void Pixel_in_screen_c64fli_bitmap_with_opt_preview(word x,word y,byte color,int preview) +{ + word startx = x & ~3; + word x2; + byte c[4]; + byte oldcolor = Read_pixel_from_current_layer(x, y); + + if (oldcolor == color) + return; // nothing to do ! + c[0] = Read_pixel_from_layer(0, x, y); + c[1] = c[0]; + c[2] = c[0]; + c[3] = Read_pixel_from_layer(1, x, y); + + Pixel_in_screen_layered_with_opt_preview(x,y,color,preview); + + // if the color is the background or the color RAM color, + // no clash is possible ! + if (color == c[0] || color == c[1]) + return; + + // check the number of color used + for (x2 = startx; x2 < startx+4; x2++) + { + int i; + byte col = Read_pixel_from_current_layer(x2, y); + // look for the color in the 4 color "palette" + for (i = 0; i < 4; i++) + { + if (col == c[i]) + break; + } + if (i >= 4) + { + if (c[1] == c[0]) + c[1] = col; // assign 1st color of Screen RAM + else if (c[2] == c[0]) + c[2] = col; // assign 2nd color of Screen RAM + else // color clash ! + { + if (oldcolor == c[0] || oldcolor == c[3]) + oldcolor = c[2]; // pick another one ! + for (x2 = startx; x2 < startx+4; x2++) + { + col = Read_pixel_from_current_layer(x2, y); + if (col == oldcolor) + Pixel_in_screen_layered_with_opt_preview(x2,y,color,preview); + } + return; + } + } + } +} + /// Paint a a single pixel in image and optionnaly on screen : in a layer under one that acts as a layer-selector (mode 5). static void Pixel_in_screen_underlay_with_opt_preview(word x,word y,byte color,int preview) { @@ -3812,7 +3894,6 @@ void Update_pixel_renderer(void) { switch (Main.backups->Pages->Image_mode) { - case IMAGE_MODE_C64FLI: //TODO case IMAGE_MODE_ANIMATION: // direct Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_direct_with_opt_preview; @@ -3848,6 +3929,14 @@ void Update_pixel_renderer(void) else // layered (again, for layers > 4 in MODE5 and RASTER) Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_layered_with_opt_preview; break; + case IMAGE_MODE_C64FLI: + if (Main.current_layer < 2) + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_c64fli_underlay_with_opt_preview; + else if (Main.current_layer == 2) + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_c64fli_bitmap_with_opt_preview; + else + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_layered_with_opt_preview; + break; case IMAGE_MODE_HGR: if (Main.current_layer == 0) // monochrome layer Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_hgr_mono_with_opt_preview; diff --git a/src/helpfile.h b/src/helpfile.h index 91fc1924..698870c7 100644 --- a/src/helpfile.h +++ b/src/helpfile.h @@ -1955,6 +1955,16 @@ static const T_Help_table helptable_effects[] = HELP_TEXT ("Game Boy sprites.") HELP_TEXT ("") HELP_TEXT ("") + HELP_BOLD ("C64 Flexible Line Interpretation (FLI)") + HELP_TEXT ("- Layer 1 contains the background colors,") + HELP_TEXT (" one per line.") + HELP_TEXT ("- Layer 2 contains the Color RAM with one") + HELP_TEXT (" color per 4x8 block.") + HELP_TEXT ("- Layer 3 contains the bitmap and Screen RAM") + HELP_TEXT (" Two colors from the Screen RAM can be used") + HELP_TEXT (" per 4x1 block.") + HELP_TEXT ("") + HELP_TEXT ("") HELP_BOLD ("Amstrad CPC Mode5") HELP_TEXT ("This mode works on 5 layers pictures with a") HELP_TEXT ("width multiple of 48.")