diff --git a/src/brush.c b/src/brush.c index 47b153b5..fc72626f 100644 --- a/src/brush.c +++ b/src/brush.c @@ -120,7 +120,8 @@ void Display_paintbrush(short x,short y,byte color) if (Mouse_K) // pas de curseur si on est en preview et return; // en train de cliquer - if (Main.backups->Pages->Image_mode == IMAGE_MODE_MODE5 && Main.current_layer < 4) + if ((Main.backups->Pages->Image_mode == IMAGE_MODE_MODE5 + || Main.backups->Pages->Image_mode == IMAGE_MODE_RASTER) && Main.current_layer < 4) { goto single_pixel; } @@ -284,7 +285,8 @@ void Draw_paintbrush(short x,short y,byte color) int position; byte old_color; - if (Main.backups->Pages->Image_mode == IMAGE_MODE_MODE5 && Main.current_layer < 4) + if ((Main.backups->Pages->Image_mode == IMAGE_MODE_MODE5 + || Main.backups->Pages->Image_mode == IMAGE_MODE_RASTER) && Main.current_layer < 4) { // Flood-fill the enclosing area if (x= 0 && y >= 0 @@ -295,41 +297,110 @@ void Draw_paintbrush(short x,short y,byte color) { short min_x,width,min_y,height; short xx,yy; - - // determine area - switch(Main.current_layer) - { - case 0: - default: - // Full layer - min_x=0; - min_y=0; - width=Main.image_width; - height=Main.image_height; - break; - case 1: - case 2: - // Line - min_x=0; - min_y=y; - width=Main.image_width; - height=1; - break; - case 3: - // Segment - min_x=x / 48 * 48; - min_y=y; - width=48; - height=1; - break; - //case 4: - // // 8x8 - // min_x=x / 8 * 8; - // min_y=y / 8 * 8; - // width=8; - // height=8; - // break; - } + + if (Main.backups->Pages->Image_mode == IMAGE_MODE_MODE5) + { + // determine area + switch(Main.current_layer) + { + case 0: + default: + // Full layer + min_x=0; + min_y=0; + width=Main.image_width; + height=Main.image_height; + break; + case 1: + case 2: + // Line + min_x=0; + min_y=y; + width=Main.image_width; + height=1; + break; + case 3: + // Segment + min_x=x / 48 * 48; + min_y=y; + width=48; + height=1; + break; + } + } else { + int prev_x; + // Raster mode + // No matter what, you can always edit only 1 line at a time here, and you will always + // draw on "nops" boundaries (8 pixels in mode 1) + height=1; + min_y=y; + min_x=x / 8 * 8; + width = 8; + + // ???????? + // ^ + // A + + // First look for the previous span to see if it is the same color + prev_x = min_x - 8; + + old_color = Read_pixel_from_current_screen(prev_x, y); + + if (old_color == color) { + // aaaA???? + // ^ + // A + // We are just making the previous span larger + width = 8; + while ((min_x >= 0) && (width < 32) + && (Read_pixel_from_current_screen(min_x, y) == color)) + { + min_x -= 8; + width += 8; + } + } else { + // ???B???? + // ^ + // A + // We are creating a new span. We need to check if the previous span is still large + // enough to be allowed. If it is less than 32 pixels, there is no way to render it + // on the real hardware (this is the time the OUT instruction to change the palette + // needs) + while ((min_x - prev_x < 48) + && (prev_x <= 0 || old_color == Read_pixel_from_current_screen(prev_x, y))) + { + prev_x -= 8; + } + prev_x += 8; + + // CBBB???? + // p ^ + // A + // The previous span is too small, so eat it + if (min_x - prev_x < 32) { + width += min_x - prev_x; + min_x = prev_x; + } + + if (width < 32) + width = 32; + } + // Now, we also need to check if the next span is still large enough, as we are going to + // remove 8 pixels from it. If it is not, we just replace it with the current color and + // let the user figure out how to reinsert it without breaking everything. + prev_x = min_x + width; + old_color = Read_pixel_from_current_screen(prev_x, y); + if (old_color != color) { + while ((prev_x - (min_x + width) < 40) + && (prev_x > Main.image_width || old_color == Read_pixel_from_current_screen(prev_x, y))) + { + prev_x += 8; + } + + if (prev_x - (min_x + width) < 32) + width = prev_x - min_x; + } + } // Clip the bottom edge. // (Necessary if image height is not a multiple) if (min_y+height>=Main.image_height) @@ -338,7 +409,7 @@ void Draw_paintbrush(short x,short y,byte color) // (Necessary if image width is not a multiple) if (min_x+width>=Main.image_width) width=Main.image_width-min_x; - + for (yy=min_y; yyPages->Image_mode != IMAGE_MODE_LAYERED || - Main.backups->Pages->Nb_layers!=5 || (Main.image_width%48)) + Main.backups->Pages->Nb_layers!=5) { - Verbose_message("Error!", "This emulation of Amstrad CPC's Mode5 can only be used on a 5-layer image whose width is a multiple of 48."); + Verbose_message("Error!", "Emulation of Amstrad CPC's rasters requires a 5-layer image."); return; } for (pixel=0; pixel < Main.image_width*Main.image_height; pixel++) { if (Main.backups->Pages->Image[4].Pixels[pixel]>3) { - Verbose_message("Error!", "This emulation of Amstrad CPC's Mode5 needs all pixels of layer 5 to use colors 0-3."); + Verbose_message("Error!", "Emulation of Amstrad CPC's rasters needs all pixels of layer 5 to use colors 0-3."); return; } } @@ -220,6 +227,7 @@ void Button_Constraint_menu(void) {IMAGE_MODE_EGX, "EGX (CPC)"}, {IMAGE_MODE_EGX2, "EGX2 (CPC)"}, {IMAGE_MODE_MODE5, "Mode 5 (CPC)"}, + {IMAGE_MODE_RASTER, "Rasters (CPC)"}, }; Open_window(154,79,"8-bit constraints"); diff --git a/src/const.h b/src/const.h index 77f68b7d..7e35f243 100644 --- a/src/const.h +++ b/src/const.h @@ -614,6 +614,7 @@ enum IMAGE_MODES IMAGE_MODE_EGX, ///< CPC EGX IMAGE_MODE_EGX2, ///< CPC EGX2 IMAGE_MODE_MODE5, ///< CPC mode 5 + IMAGE_MODE_RASTER, ///< CPC generic rasters }; /// Circle / Ellipse Modes diff --git a/src/graph.c b/src/graph.c index f5a867a3..4401d1bf 100644 --- a/src/graph.c +++ b/src/graph.c @@ -3213,7 +3213,8 @@ byte Read_pixel_from_current_screen (word x,word y) return *((y)*Main.image_width+(x)+Main.backups->Pages->Image[Main.current_layer].Pixels); } - 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) if (Main.current_layer==4) return *(Main.backups->Pages->Image[Main.current_layer].Pixels + x+y*Main.image_width); @@ -3632,7 +3633,7 @@ void Update_pixel_renderer(void) Pixel_in_current_screen = Pixel_in_screen_zx; Pixel_in_current_screen_with_preview = Pixel_in_screen_zx_with_preview; } - // Implicit else : Image_mode must be IMAGE_MODE_MODE5 + // Implicit else : Image_mode must be IMAGE_MODE_MODE5 or IMAGE_MODE_RASTER else if ( Main.current_layer == 4) { // overlay @@ -3647,7 +3648,7 @@ void Update_pixel_renderer(void) } else { - // layered (again, for layers > 4 in MODE5) + // layered (again, for layers > 4 in MODE5 and RASTER) Pixel_in_current_screen = Pixel_in_screen_layered; Pixel_in_current_screen_with_preview = Pixel_in_screen_layered_with_preview; } diff --git a/src/pages.c b/src/pages.c index 042d46eb..235c59ce 100644 --- a/src/pages.c +++ b/src/pages.c @@ -203,7 +203,8 @@ void Redraw_layered_image(void) // Re-construct the image with the visible layers byte layer=0; // First layer - if (Main.backups->Pages->Image_mode == IMAGE_MODE_MODE5 && Main.layers_visible & (1<<4)) + if ((Main.backups->Pages->Image_mode == IMAGE_MODE_MODE5 + || Main.backups->Pages->Image_mode == IMAGE_MODE_RASTER) && Main.layers_visible & (1<<4)) { // The raster result layer is visible: start there // Copy it in Main_visible_image @@ -1453,7 +1454,7 @@ byte Delete_layer(T_List_of_pages *list, int layer) Spare.current_layer--; new_current_layer = Spare.current_layer; } - + // Fun with binary! layers_before = ((1<>1; @@ -1461,11 +1462,12 @@ byte Delete_layer(T_List_of_pages *list, int layer) // Ensure the current layer is part what is shown. *visible_layers_flag |= 1<Pages->Image_mode) @@ -1486,18 +1489,12 @@ void Switch_layer_mode(enum IMAGE_MODES new_mode) Main.backups->Pages->Image_mode = new_mode; - switch (new_mode) + if (new_mode != IMAGE_MODE_ANIMATION) { - case IMAGE_MODE_MODE5: - case IMAGE_MODE_LAYERED: - default: Update_buffers(Main.image_width, Main.image_height); Redraw_layered_image(); - break; - case IMAGE_MODE_ANIMATION: - // nothing to do. - // Eventually, we may clear the buffers to save a bit of memory... - break; } - Update_pixel_renderer(); + // TODO Eventually, in animation mode we may clear the buffers to save a bit of memory... + + Update_pixel_renderer(); } diff --git a/src/palette.c b/src/palette.c index 0efb46d2..2045079f 100644 --- a/src/palette.c +++ b/src/palette.c @@ -345,7 +345,8 @@ void Remap_image_highlevel(byte * conversion_table) // Remap the flatenned image view if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION - && Main.backups->Pages->Image_mode != IMAGE_MODE_MODE5) + && Main.backups->Pages->Image_mode != IMAGE_MODE_MODE5 + && Main.backups->Pages->Image_mode != IMAGE_MODE_RASTER) { Remap_general_lowlevel(conversion_table,Main.visible_image.Image,Main.visible_image.Image, Main.image_width,Main.image_height,Main.image_width);