Constraint modes: Thomson, ZX

This commit is contained in:
Adrien Destugues 2017-05-28 11:11:03 +02:00
parent 9e55b2d995
commit f2b04e08d0
4 changed files with 209 additions and 20 deletions

View File

@ -5610,5 +5610,6 @@ void Button_Brush_container(void)
byte Any_effect_active(void) byte Any_effect_active(void)
{ {
return Shade_mode||Quick_shade_mode||Colorize_mode||Smooth_mode||Tiling_mode||Smear_mode||Stencil_mode||Mask_mode||Sieve_mode||Snap_mode||Main_tilemap_mode; return Shade_mode||Quick_shade_mode||Colorize_mode||Smooth_mode||Tiling_mode||Smear_mode
||Stencil_mode||Mask_mode||Sieve_mode||Snap_mode||Main_tilemap_mode || (Main_backups->Pages->Image_mode > IMAGE_MODE_ANIMATION);
} }

View File

@ -215,11 +215,12 @@ void Button_Constraint_menu(void)
Window_set_normal_button(82,55,51,14,"OK" ,0,1,SDLK_RETURN); // 2 Window_set_normal_button(82,55,51,14,"OK" ,0,1,SDLK_RETURN); // 2
dropdown = Window_set_dropdown_button(17, 21, 120, 14, 120, "Constraints", 1, 0, 1, RIGHT_SIDE|LEFT_SIDE, 0); // 3 dropdown = Window_set_dropdown_button(17, 21, 120, 14, 120, "Constraints", 1, 0, 1, RIGHT_SIDE|LEFT_SIDE, 0); // 3
//Window_dropdown_add_item(dropdown, IMAGE_MODE_ZX, "ZX Spectrum"); Window_dropdown_add_item(dropdown, IMAGE_MODE_ZX, "ZX Spectrum");
//Window_dropdown_add_item(dropdown, IMAGE_MODE_GBC, "Game Boy Color"); //Window_dropdown_add_item(dropdown, IMAGE_MODE_GBC, "Game Boy Color");
Window_dropdown_add_item(dropdown, IMAGE_MODE_EGX, "EGX (CPC)"); Window_dropdown_add_item(dropdown, IMAGE_MODE_THOMSON, "40col (MO/TO)");
Window_dropdown_add_item(dropdown, IMAGE_MODE_EGX2, "EGX2 (CPC)"); Window_dropdown_add_item(dropdown, IMAGE_MODE_EGX, "EGX (CPC)");
Window_dropdown_add_item(dropdown, IMAGE_MODE_MODE5, "Mode 5 (CPC)"); Window_dropdown_add_item(dropdown, IMAGE_MODE_EGX2, "EGX2 (CPC)");
Window_dropdown_add_item(dropdown, IMAGE_MODE_MODE5, "Mode 5 (CPC)");
Update_window_area(0,0,Window_width, Window_height); Update_window_area(0,0,Window_width, Window_height);
Display_cursor(); Display_cursor();
@ -237,6 +238,8 @@ void Button_Constraint_menu(void)
if (clicked_button==2) // OK if (clicked_button==2) // OK
{ {
if ((Selected_Constraint_Mode > IMAGE_MODE_ANIMATION)
&& (Main_backups->Pages->Image_mode <= IMAGE_MODE_ANIMATION))
Button_Constraint_mode(); Button_Constraint_mode();
} }

View File

@ -591,6 +591,7 @@ enum IMAGE_MODES
IMAGE_MODE_ANIMATION, ///< Animation IMAGE_MODE_ANIMATION, ///< Animation
IMAGE_MODE_ZX, ///< ZX Spectrum (note "SPECTRUM" is kept for later... Spectrum 512 anyone?) IMAGE_MODE_ZX, ///< ZX Spectrum (note "SPECTRUM" is kept for later... Spectrum 512 anyone?)
IMAGE_MODE_GBC, ///< Game Boy Color IMAGE_MODE_GBC, ///< Game Boy Color
IMAGE_MODE_THOMSON, ///< "40 columns" mode on Thomson machines
IMAGE_MODE_EGX, ///< CPC EGX IMAGE_MODE_EGX, ///< CPC EGX
IMAGE_MODE_EGX2, ///< CPC EGX2 IMAGE_MODE_EGX2, ///< CPC EGX2
IMAGE_MODE_MODE5, ///< CPC mode 5 IMAGE_MODE_MODE5, ///< CPC mode 5

View File

@ -59,8 +59,11 @@
// Generic pixel-drawing function. // Generic pixel-drawing function.
Func_pixel Pixel_figure; Func_pixel Pixel_figure;
// Fonction qui met à jour la zone de l'image donnée en paramètre sur l'écran. /** Update the picture on screen, for the area passed in parameters.
// Tient compte du décalage X et Y et du zoom, et fait tous les controles nécessaires *
* Takes into account the X/Y scrolling and zoom, and performs all safety checks so no updates will
* go outside the display area.
*/
void Update_part_of_screen(short x, short y, short width, short height) void Update_part_of_screen(short x, short y, short width, short height)
{ {
short effective_w, effective_h; short effective_w, effective_h;
@ -68,7 +71,7 @@ void Update_part_of_screen(short x, short y, short width, short height)
short effective_Y; short effective_Y;
short diff; short diff;
// Première étape, si L ou H est négatif, on doit remettre la zone à l'endroit // First make sure the zone is in forward direction (positive width/height)
if (width < 0) if (width < 0)
{ {
x += width; x += width;
@ -81,7 +84,14 @@ void Update_part_of_screen(short x, short y, short width, short height)
height = - height; height = - height;
} }
// D'abord on met à jour dans la zone écran normale // Round up to a multiple of 8 pixels, because some special modes (ZX, Thomson, ...) can change
// more pixels than expected (attribute clash)
x &= 0xFFF8;
y &= 0xFFF8;
width = ((width - 1) | 0x7) + 1;
height = ((height - 1) | 0x7) + 1;
// Update "normal" view
diff = x-Main_offset_X; diff = x-Main_offset_X;
if (diff<0) if (diff<0)
{ {
@ -105,10 +115,10 @@ void Update_part_of_screen(short x, short y, short width, short height)
effective_Y = diff; effective_Y = diff;
} }
// Normalement il ne faudrait pas updater au delà du split quand on est en mode loupe, // Clamp to actually visible area. All tools are normally constrained to this, but there are some
// mais personne ne devrait demander d'update en dehors de cette limite, même le fill est contraint // exceptions:
// a rester dans la zone visible de l'image // - Brush preview requests updates outside the visible screen,
// ...Sauf l'affichage de brosse en preview - yr // - ZX/Thomson constraints can lead to pixel changes outside the visible area.
if(Main_magnifier_mode && effective_X + effective_w > Main_separator_position) if(Main_magnifier_mode && effective_X + effective_w > Main_separator_position)
effective_w = Main_separator_position - effective_X; effective_w = Main_separator_position - effective_X;
else if(effective_X + effective_w > Screen_width) else if(effective_X + effective_w > Screen_width)
@ -116,8 +126,8 @@ void Update_part_of_screen(short x, short y, short width, short height)
if(effective_Y + effective_h > Menu_Y) if(effective_Y + effective_h > Menu_Y)
effective_h = Menu_Y - effective_Y; effective_h = Menu_Y - effective_Y;
/* /* (for debug purposes, highlight the rectangle that is updated)
SDL_Rect r; SDL_Rect r;
r.x=effective_X; r.x=effective_X;
r.y=effective_Y; r.y=effective_Y;
@ -127,15 +137,16 @@ void Update_part_of_screen(short x, short y, short width, short height)
*/ */
Update_rect(effective_X,effective_Y,effective_w,effective_h); Update_rect(effective_X,effective_Y,effective_w,effective_h);
// Et ensuite dans la partie zoomée // Now update the "zoomed" part of the display
if(Main_magnifier_mode) if(Main_magnifier_mode)
{ {
// Clipping en X // Convert picture to zoomed-screen coordinates
effective_X = (x-Main_magnifier_offset_X)*Main_magnifier_factor; effective_X = (x-Main_magnifier_offset_X)*Main_magnifier_factor;
effective_Y = (y-Main_magnifier_offset_Y)*Main_magnifier_factor; effective_Y = (y-Main_magnifier_offset_Y)*Main_magnifier_factor;
effective_w = width * Main_magnifier_factor; effective_w = width * Main_magnifier_factor;
effective_h = height * Main_magnifier_factor; effective_h = height * Main_magnifier_factor;
// Apply horizontal clipping
if (effective_X < 0) if (effective_X < 0)
{ {
effective_w+=effective_X; effective_w+=effective_X;
@ -155,7 +166,7 @@ void Update_part_of_screen(short x, short y, short width, short height)
} }
// Clipping en Y // Vertical clipping
if (effective_Y < 0) if (effective_Y < 0)
{ {
effective_h+=effective_Y; effective_h+=effective_Y;
@ -172,7 +183,7 @@ void Update_part_of_screen(short x, short y, short width, short height)
} }
// Très utile pour le debug :) // Again, for debugging purposes, display the touched rectangle
/*SDL_Rect r; /*SDL_Rect r;
r.x=effective_X; r.x=effective_X;
r.y=effective_Y; r.y=effective_Y;
@ -3041,6 +3052,167 @@ void Pixel_in_screen_egx_with_preview(word x,word y,byte color)
Pixel_in_screen_layered_with_preview(x,y,color & mask); Pixel_in_screen_layered_with_preview(x,y,color & mask);
} }
void Pixel_in_screen_thomson(word x,word y,byte color)
{
word start = x & 0xFFF8;
word x2;
uint8_t c1, c2;
// The color we are going to replace
c1 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + x+y*Main_image_width);
if (c1 == color)
return;
for (x2 = 0; x2 < 8; x2++)
{
c2 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + (x2+start)+y*Main_image_width);
if (c2 == color)
continue;
if (c2 != c1)
break;
}
if (c2 == c1 || c2 == color)
{
// There was only one color, so we can add a second one.
Pixel_in_screen_layered(x,y,color);
return;
}
for (x2 = 0; x2 < 8; x2++)
{
c2 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + (x2+start)+y*Main_image_width);
if (c2 == c1) {
Pixel_in_screen_layered(x2+start,y,color);
}
}
}
void Pixel_in_screen_thomson_with_preview(word x,word y,byte color)
{
word start = x & 0xFFF8;
word x2;
uint8_t c1, c2;
// The color we are going to replace
c1 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + x+y*Main_image_width);
if (c1 == color)
return;
for (x2 = 0; x2 < 8; x2++)
{
c2 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + (x2+start)+y*Main_image_width);
if (c2 == color)
continue;
if (c2 != c1)
break;
}
if (c2 == c1 || c2 == color)
{
// There was only one color, so we can add a second one.
Pixel_in_screen_layered_with_preview(x,y,color);
return;
}
for (x2 = 0; x2 < 8; x2++)
{
c2 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + (x2+start)+y*Main_image_width);
if (c2 == c1) {
Pixel_in_screen_layered_with_preview(x2+start,y,color);
}
}
}
void Pixel_in_screen_zx(word x,word y,byte color)
{
word start = x & 0xFFF8;
word starty = y & 0xFFF8;
word x2, y2;
uint8_t c1, c2;
// The color we are going to replace
c1 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + x+y*Main_image_width);
if (c1 == color)
return;
for (x2 = 0; x2 < 8; x2++)
for (y2 = 0; y2 < 8; y2++)
{
c2 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + (x2+start)+(y2+starty)*Main_image_width);
if (c2 == color)
continue;
if (c2 != c1)
goto done;
}
done:
if (c2 == c1 || c2 == color)
{
// There was only one color, so we can add a second one.
Pixel_in_screen_layered(x,y,color);
return;
}
for (x2 = 0; x2 < 8; x2++)
for (y2 = 0; y2 < 8; y2++)
{
c2 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + (x2+start)+(y2+starty)*Main_image_width);
if (c2 == c1) {
Pixel_in_screen_layered(x2+start,y2+starty,color);
}
}
}
void Pixel_in_screen_zx_with_preview(word x,word y,byte color)
{
word start = x & 0xFFF8;
word starty = y & 0xFFF8;
word x2,y2;
uint8_t c1, c2;
// The color we are going to replace
c1 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + x+y*Main_image_width);
// Pixel is already of the wanted color: nothing to do
if (c1 == color)
return;
// Check the whole cell
for (x2 = 0; x2 < 8; x2++)
for (y2 = 0; y2 < 8; y2++)
{
c2 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + (x2+start)+(y2+starty)*Main_image_width);
// Pixel is already of the color we are going to add, it is no problem
if (c2 == color)
continue;
// We have found another color, which is the one we will keep from the cell
if (c2 != c1)
goto done;
}
done:
if (c2 == c1 || c2 == color)
{
// There was only one color, so we can add a second one.
Pixel_in_screen_layered_with_preview(x,y,color);
return;
}
// Replace all C1 with C2
for (x2 = 0; x2 < 8; x2++)
for (y2 = 0; y2 < 8; y2++)
{
c2 = *(Main_backups->Pages->Image[Main_current_layer].Pixels + (x2+start)+(y2+starty)*Main_image_width);
if (c2 == c1) {
Pixel_in_screen_layered_with_preview(x2+start,y2+starty,color);
}
}
}
/// Paint a a single pixel in image only : in a layer under one that acts as a layer-selector (mode 5). /// Paint a a single pixel in image only : in a layer under one that acts as a layer-selector (mode 5).
void Pixel_in_screen_underlay(word x,word y,byte color) void Pixel_in_screen_underlay(word x,word y,byte color)
{ {
@ -3150,10 +3322,22 @@ void Update_pixel_renderer(void)
if (Main_backups->Pages->Image_mode == IMAGE_MODE_EGX if (Main_backups->Pages->Image_mode == IMAGE_MODE_EGX
|| Main_backups->Pages->Image_mode == IMAGE_MODE_EGX2) || Main_backups->Pages->Image_mode == IMAGE_MODE_EGX2)
{ {
// layered // special "EGX" mode
Pixel_in_current_screen = Pixel_in_screen_egx; Pixel_in_current_screen = Pixel_in_screen_egx;
Pixel_in_current_screen_with_preview = Pixel_in_screen_egx_with_preview; Pixel_in_current_screen_with_preview = Pixel_in_screen_egx_with_preview;
} }
else
if (Main_backups->Pages->Image_mode == IMAGE_MODE_THOMSON)
{
Pixel_in_current_screen = Pixel_in_screen_thomson;
Pixel_in_current_screen_with_preview = Pixel_in_screen_thomson_with_preview;
}
else
if (Main_backups->Pages->Image_mode == IMAGE_MODE_ZX)
{
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
else if ( Main_current_layer == 4) else if ( Main_current_layer == 4)
{ {