From 8453575812e19930d4b0146f1cac5c2571ea9547 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 22 Nov 2018 11:08:53 +0100 Subject: [PATCH] implement C64 Multicolor constraints drawing mode --- src/buttons_effects.c | 16 ++++----- src/graph.c | 83 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 9 deletions(-) diff --git a/src/buttons_effects.c b/src/buttons_effects.c index 3b2020c2..e8a585a0 100644 --- a/src/buttons_effects.c +++ b/src/buttons_effects.c @@ -224,16 +224,16 @@ void Button_Constraint_menu(void) const char * label; const char * summary; } modes[] = { - {IMAGE_MODE_ZX, "ZX Spectrum", "2 colors per 8x8 block"}, + {IMAGE_MODE_ZX, "ZX Spectrum", "2 colors per 8x8 block"}, // 256x192 //{IMAGE_MODE_GBC, "Game Boy Color"}, - {IMAGE_MODE_THOMSON, "40col (MO/TO)", "2 colors per 8x1 block"}, - {IMAGE_MODE_EGX, "EGX (CPC)", "Alternate Mode0/Mode1 "}, - {IMAGE_MODE_EGX2, "EGX2 (CPC)", "Alternate Mode1/Mode2 "}, - {IMAGE_MODE_MODE5, "Mode 5 (CPC)", "Mode5 "}, + {IMAGE_MODE_THOMSON, "40col (MO/TO)", "2 colors per 8x1 block"}, // 320x200 + {IMAGE_MODE_EGX, "EGX (CPC)", "Alternate Mode0/Mode1 "}, // 320x200 + {IMAGE_MODE_EGX2, "EGX2 (CPC)", "Alternate Mode1/Mode2 "}, // 640x200 + {IMAGE_MODE_MODE5, "Mode 5 (CPC)", "Mode5 "}, // 288x256 {IMAGE_MODE_RASTER, "Rasters (CPC)", "CPC Rasters "}, - {IMAGE_MODE_C64HIRES,"C64 HiRes", "2 colors per 8x8 block"}, - {IMAGE_MODE_C64MULTI,"C64 Multicolor","4 colors per 4x1 block"}, - {IMAGE_MODE_C64FLI, "C64 FLI", "improved multicolor "}, + {IMAGE_MODE_C64HIRES,"C64 HiRes", "2 colors per 8x8 block"}, // 320x200 + {IMAGE_MODE_C64MULTI,"C64 Multicolor","4 colors per 4x1 block"}, // 160x200 + //{IMAGE_MODE_C64FLI, "C64 FLI", "improved multicolor "}, // 160x200 }; Open_window(194,95,"8-bit constraints"); diff --git a/src/graph.c b/src/graph.c index 0bd59cb8..5799bb35 100644 --- a/src/graph.c +++ b/src/graph.c @@ -3257,6 +3257,11 @@ static void Pixel_in_screen_layered_with_opt_preview(word x,word y,byte color, i } } + +/// @defgroup constraints Special constaints drawing modes +/// For 8bits machines modes (ZX Spectrum, C64, etc.) +/// @{ + /// Paint a pixel in CPC EGX mode /// /// even lines have 2x more pixel than odd lines, but less colors @@ -3382,6 +3387,77 @@ done: } } +/// Paint a pixel with C64 MultiColor constraints +/// +/// Only 4 colors in a 4x8 block, including the background color +/// which is common for all blocks. +/// +/// @todo support for any background color (fixed to 0 now) +static void Pixel_in_screen_c64multi_with_opt_preview(word x,word y,byte color,int preview) +{ + word startx = x & ~3; + word starty = y & ~7; + word x2, y2; + byte col, old_color; + byte c[4] = { 0, 0, 0, 0 }; // palette of 4 colors for the block + int i, n; + + old_color = Read_pixel_from_current_layer(x, y); + if (old_color == color) + return; // nothing to do if the color doesn't change ! + + c[0] = 0; // assume background is 0 + n = 1; // counted colors + for (y2 = 0; y2 < 8; y2++) + { + for (x2 = 0; x2 < 4; x2++) + { + col = Read_pixel_from_current_layer(startx+x2, starty+y2); + // search color in our mini 4 colors palette + for (i = 0; i < n; i++) + { + if (col == c[i]) + break; // found + } + if (i == n) // not found + { + if (n < 4) + c[n++] = col; // set color in palette + else // already more than 3 colors (+ background) in the block. Fix it + Pixel_in_screen_layered_with_opt_preview(startx+x2,starty+y2,color,preview); + } + } + } + if (n < 4) + { + // there is less than 4 colors in the block : nothing special to do + Pixel_in_screen_layered_with_opt_preview(x,y,color,preview); + return; + } + for (i = 0; i < n; i++) + if (color == c[i]) + { + // The new color is already in the palette, nothing special to do + Pixel_in_screen_layered_with_opt_preview(x,y,color,preview); + return; + } + // The execution reaches this point only if plotting the new color + // would violate the constraints. + // replace old_color with color, except if old_color is the background. + // replace the last color of the palette instead. + if (old_color == c[0]) // background + old_color = c[3]; + for (y2 = 0; y2 < 8; y2++) + { + for (x2 = 0; x2 < 4; x2++) + { + col = Read_pixel_from_current_layer(startx+x2, starty+y2); + if (col == old_color) + Pixel_in_screen_layered_with_opt_preview(startx+x2,starty+y2,color,preview); + } + } +} + /// 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) { @@ -3422,6 +3498,9 @@ static void Pixel_in_screen_overlay_with_opt_preview(word x,word y,byte color,in } } +// end of constraints group +/// @} + Func_pixel_opt_preview Pixel_in_current_screen_with_opt_preview=Pixel_in_screen_direct_with_opt_preview; void Pixel_in_spare(word x,word y, byte color) @@ -3443,7 +3522,6 @@ void Update_pixel_renderer(void) { switch (Main.backups->Pages->Image_mode) { - case IMAGE_MODE_C64MULTI: //TODO case IMAGE_MODE_C64FLI: //TODO case IMAGE_MODE_GBC: // TODO case IMAGE_MODE_ANIMATION: @@ -3466,6 +3544,9 @@ void Update_pixel_renderer(void) case IMAGE_MODE_ZX: Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_zx_with_opt_preview; break; + case IMAGE_MODE_C64MULTI: + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_c64multi_with_opt_preview; + break; case IMAGE_MODE_MODE5: case IMAGE_MODE_RASTER: if ( Main.current_layer == 4) // overlay