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)
{
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
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_EGX, "EGX (CPC)");
Window_dropdown_add_item(dropdown, IMAGE_MODE_EGX2, "EGX2 (CPC)");
Window_dropdown_add_item(dropdown, IMAGE_MODE_MODE5, "Mode 5 (CPC)");
Window_dropdown_add_item(dropdown, IMAGE_MODE_THOMSON, "40col (MO/TO)");
Window_dropdown_add_item(dropdown, IMAGE_MODE_EGX, "EGX (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);
Display_cursor();
@ -237,6 +238,8 @@ void Button_Constraint_menu(void)
if (clicked_button==2) // OK
{
if ((Selected_Constraint_Mode > IMAGE_MODE_ANIMATION)
&& (Main_backups->Pages->Image_mode <= IMAGE_MODE_ANIMATION))
Button_Constraint_mode();
}

View File

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

View File

@ -59,8 +59,11 @@
// Generic pixel-drawing function.
Func_pixel Pixel_figure;
// Fonction qui met à jour la zone de l'image donnée en paramètre sur l'écran.
// Tient compte du décalage X et Y et du zoom, et fait tous les controles nécessaires
/** Update the picture on screen, for the area passed in parameters.
*
* 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)
{
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 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)
{
x += width;
@ -81,7 +84,14 @@ void Update_part_of_screen(short x, short y, short width, short 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;
if (diff<0)
{
@ -105,10 +115,10 @@ void Update_part_of_screen(short x, short y, short width, short height)
effective_Y = diff;
}
// Normalement il ne faudrait pas updater au delà du split quand on est en mode loupe,
// mais personne ne devrait demander d'update en dehors de cette limite, même le fill est contraint
// a rester dans la zone visible de l'image
// ...Sauf l'affichage de brosse en preview - yr
// Clamp to actually visible area. All tools are normally constrained to this, but there are some
// exceptions:
// - Brush preview requests updates outside the visible screen,
// - ZX/Thomson constraints can lead to pixel changes outside the visible area.
if(Main_magnifier_mode && effective_X + effective_w > Main_separator_position)
effective_w = Main_separator_position - effective_X;
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)
effective_h = Menu_Y - effective_Y;
/*
/* (for debug purposes, highlight the rectangle that is updated)
SDL_Rect r;
r.x=effective_X;
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);
// Et ensuite dans la partie zoomée
// Now update the "zoomed" part of the display
if(Main_magnifier_mode)
{
// Clipping en X
// Convert picture to zoomed-screen coordinates
effective_X = (x-Main_magnifier_offset_X)*Main_magnifier_factor;
effective_Y = (y-Main_magnifier_offset_Y)*Main_magnifier_factor;
effective_w = width * Main_magnifier_factor;
effective_h = height * Main_magnifier_factor;
// Apply horizontal clipping
if (effective_X < 0)
{
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)
{
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;
r.x=effective_X;
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);
}
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).
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
|| Main_backups->Pages->Image_mode == IMAGE_MODE_EGX2)
{
// layered
// special "EGX" mode
Pixel_in_current_screen = Pixel_in_screen_egx;
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
else if ( Main_current_layer == 4)
{