diff --git a/const.h b/const.h index ff6d5483..20892d2f 100644 --- a/const.h +++ b/const.h @@ -95,14 +95,14 @@ // -- File formats #ifndef __no_pnglib__ +#define NB_KNOWN_FORMATS 15 ///< Total number of known file formats. +#define NB_FORMATS_LOAD 15 ///< Number of file formats that grafx2 can load. +#define NB_FORMATS_SAVE 15 ///< Number of file formats that grafx2 can save. +#else +// Without pnglib #define NB_KNOWN_FORMATS 14 ///< Total number of known file formats. #define NB_FORMATS_LOAD 14 ///< Number of file formats that grafx2 can load. #define NB_FORMATS_SAVE 14 ///< Number of file formats that grafx2 can save. -#else -// Without pnglib -#define NB_KNOWN_FORMATS 13 ///< Total number of known file formats. -#define NB_FORMATS_LOAD 13 ///< Number of file formats that grafx2 can load. -#define NB_FORMATS_SAVE 13 ///< Number of file formats that grafx2 can save. #endif /// List of file formats recognized by grafx2 @@ -122,6 +122,7 @@ enum FILE_FORMATS FORMAT_NEO, FORMAT_KCF, FORMAT_PAL, + FORMAT_C64, FORMAT_PNG }; diff --git a/gfx2.cfg b/gfx2.cfg index e8e9b110..eacf653b 100644 Binary files a/gfx2.cfg and b/gfx2.cfg differ diff --git a/loadsave.c b/loadsave.c index 175dedfe..81767e2c 100644 --- a/loadsave.c +++ b/loadsave.c @@ -109,6 +109,11 @@ void Test_NEO(void); void Load_NEO(void); void Save_NEO(void); +// -- C64 ------------------------------------------------------------------- +void Test_C64(void); +void Load_C64(void); +void Save_C64(void); + // -- PNG ------------------------------------------------------------------- #ifndef __no_pnglib__ void Test_PNG(void); @@ -132,6 +137,7 @@ T_Format File_formats[NB_KNOWN_FORMATS] = { {"neo", Test_NEO, Load_NEO, Save_NEO, 1, 0}, {"kcf", Test_KCF, Load_KCF, Save_KCF, 0, 0}, {"pal", Test_PAL, Load_PAL, Save_PAL, 0, 0}, + {"c64", Test_C64, Load_C64, Save_C64, 1, 0}, #ifndef __no_pnglib__ {"png", Test_PNG, Load_PNG, Save_PNG, 1, 1} #endif @@ -628,50 +634,53 @@ void Load_image(byte image) } else { - // Cas d'un chargement dans la brosse - if (Convert_24b_bitmap_to_256(Brush,Buffer_image_24b,Brush_width,Brush_height,Main_palette)) - File_error=2; + // Cas d'un chargement dans la brosse + if (Convert_24b_bitmap_to_256(Brush, Buffer_image_24b, Brush_width, + Brush_height, Main_palette)) + File_error = 2; } //if (!File_error) - // Palette_256_to_64(Main_palette); + // Palette_256_to_64(Main_palette); // Normalement plus besoin car 256 color natif, et c'etait probablement // un bug - yr } - free(Buffer_image_24b); - } + free(Buffer_image_24b); + } - if (image) - { + if (image) + { if ( (File_error!=1) && (File_formats[format].Backup_done) ) { if (Pixel_load_function==Pixel_load_in_preview) { - dword color_usage[256]; - Count_used_colors_area(color_usage,Preview_pos_X,Preview_pos_Y,Main_image_width/Preview_factor_X,Main_image_height/Preview_factor_Y); + dword color_usage[256]; + Count_used_colors_screen_area(color_usage, Preview_pos_X, + Preview_pos_Y, Main_image_width / Preview_factor_X, + Main_image_height / Preview_factor_Y); //Count_used_colors(color_usage); Display_cursor(); - Set_nice_menu_colors(color_usage,1); + Set_nice_menu_colors(color_usage, 1); Hide_cursor(); } // On considère que l'image chargée n'est plus modifiée - Main_image_is_modified=0; + Main_image_is_modified = 0; // Et on documente la variable Main_fileformat avec la valeur: - Main_fileformat=format+1; + Main_fileformat = format + 1; // Correction des dimensions if (Main_image_width<1) - Main_image_width=1; + Main_image_width = 1; if (Main_image_height<1) - Main_image_height=1; + Main_image_height = 1; } else if (File_error!=1) { // On considère que l'image chargée est encore modifiée - Main_image_is_modified=1; + Main_image_is_modified = 1; // Et on documente la variable Main_fileformat avec la valeur: - Main_fileformat=format+1; + Main_fileformat = format + 1; } else { @@ -5830,6 +5839,368 @@ void Save_NEO(void) } } +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +//////////////////////////////////// C64 //////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +void Test_C64(void) +{ + FILE* file; + char filename[MAX_PATH_CHARACTERS]; + long file_size; + + Get_full_filename(filename,0); + + file = fopen(filename,"rb"); + + if(file) + { + file_size = File_length_file(file); + switch(file_size) + { + case 8000: // raw bitmap + case 8002: // raw bitmap with loadaddr + case 9000: // bitmap + screen + case 9002: // bitmap + screen + loadaddr + case 10001: // multicolor + case 10003: // multicolor + loadaddr + File_error = 0; + break; + default: // then we don't know for now. + File_error = 1; + + } + fclose(file); + } + else + { + File_error = 1; + } +} + +void Load_C64_hires(byte *bitmap, byte *colors) +{ + int cx,cy,x,y,c[4],pixel,color; + + for(cy=0; cy<25; cy++) + { + for(cx=0; cx<40; cx++) + { + c[1]=colors[cy*40+cx]&15; + c[0]=colors[cy*40+cx]>>4; + for(y=0; y<8; y++) + { + pixel=bitmap[cy*320+cx*8+y]; + for(x=0; x<8; x++) + { + color=c[pixel&(1<<(7-x))?1:0]; + Pixel_load_function(cx*8+x,cy*8+y,color); + } + } + } + } +} + +void Load_C64_multi(byte *bitmap, byte *colors, byte *nybble, byte background) +{ + int cx,cy,x,y,c[4],pixel,color; + c[0]=background; + for(cy=0; cy<25; cy++) + { + for(cx=0; cx<40; cx++) + { + c[1]=colors[cy*40+cx]>>4; + c[2]=colors[cy*40+cx]&15; + c[3]=nybble[cy*40+cx]; + + for(y=0; y<8; y++) + { + pixel=bitmap[cy*320+cx*8+y]; + for(x=0; x<4; x++) + { + + color=c[(pixel&3)]; + pixel>>=2; + Pixel_load_function(cx*4+(3-x),cy*8+y,color); + } + } + } + } +} + +void Load_C64(void) +{ + FILE* file; + char filename[MAX_PATH_CHARACTERS]; + long file_size; + int newPixel_ratio; + byte background; + + // Palette from http://www.pepto.de/projects/colorvic/ + byte pal[48]={ + 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, + 0x68, 0x37, 0x2B, + 0x70, 0xA4, 0xB2, + 0x6F, 0x3D, 0x86, + 0x58, 0x8D, 0x43, + 0x35, 0x28, 0x79, + 0xB8, 0xC7, 0x6F, + 0x6F, 0x4F, 0x25, + 0x43, 0x39, 0x00, + 0x9A, 0x67, 0x59, + 0x44, 0x44, 0x44, + 0x6C, 0x6C, 0x6C, + 0x9A, 0xD2, 0x84, + 0x6C, 0x5E, 0xB5, + 0x95, 0x95, 0x95}; + + byte bitmap[8000],colors[1000],nybble[1000]; + word width=320, height=200; + + Get_full_filename(filename,0); + file = fopen(filename,"rb"); + + if(file) + { + + memcpy(Main_palette,pal,48); // this set the software palette for grafx2 + Set_palette(Main_palette); // this set the hardware palette for SDL + Remap_fileselector(); // Always call it if you change the palette + + file_size = File_length_file(file); + + if(file_size>9002)width=160; + + Init_preview(width, height, file_size, FORMAT_C64); // Do this as soon as you can + + Main_image_width = width ; + Main_image_height = height; + + Read_bytes(file,bitmap,8000); + if(file_size>8002)Read_bytes(file,colors,1000); + + if(width==160) + { + Read_bytes(file,nybble,1000); + Read_byte(file,&background); + Load_C64_multi(bitmap,colors,nybble,background); + newPixel_ratio = PIXEL_WIDE; + } + else + { + Load_C64_hires(bitmap,colors); + newPixel_ratio = PIXEL_SIMPLE; + } + + //Pixel_ratio = newPixel_ratio; + + File_error = 0; + fclose(file); + } + else + File_error = 1; +} + +int Save_C64_hires(FILE *file) +{ + int cx,cy,x,y,c1,c2,i,pixel,bits; + word numcolors; + dword cusage[256]; + byte colors[1000]; + + for(x=0;x<1000;x++)colors[x]=1; // init colormem to black/white + + for(cy=0; cy<25; cy++) // Character line, 25 lines + { + for(cx=0; cx<40; cx++) // Character column, 40 columns + { + for(i=0;i<256;i++) cusage[i]=0; + + numcolors=Count_used_colors_area(cusage,cx*8,cy*8,8,8); + if(numcolors>2) + { + Warning_message("More than 2 colors in 8x8 pixels"); + // TODO here we should hilite the offending block + printf("\nerror at %dx%d (%d colors)\n",cx*8,cy*8,numcolors); + return 1; + } + for(i=0;i<16;i++) + { + if(cusage[i]) + { + c2=i; + break; + } + } + c1=c2; + for(i=c2+1;i<16;i++) + { + if(cusage[i]) + { + c1=i; + + } + } + colors[cx+cy*40]=(c2<<4)|c1; + + for(y=0; y<8; y++) + { + bits=0; + for(x=0; x<8; x++) + { + pixel=Read_pixel_function(x+cx*8,y+cy*8); + if(pixel>15) + { + Warning_message("Color above 15 used"); + // TODO hilite offending block here too? + // or make it smarter with color allocation? + // However, the palette is fixed to the 16 first colors + return 1; + } + bits=bits<<1; + if(pixel==c1) bits|=1; + } + Write_byte(file,bits&255); + } + } + } + Write_bytes(file,colors,1000); + return 0; +} + +int Save_C64_multi(FILE *file) +{ +/* +BITS COLOR INFORMATION COMES FROM +00 Background color #0 (screen color) +01 Upper 4 bits of screen memory +10 Lower 4 bits of screen memory +11 Color nybble (nybble = 1/2 byte = 4 bits) +*/ + + int cx,cy,x,y,c[4]={0,0,0,0},color,lut[16],bits,pixel; + byte screen[1000],nybble[1000]; + word numcolors,count; + dword cusage[256]; + byte i,background=0; + numcolors=Count_used_colors(cusage); + + count=0; + for(x=0;x<16;x++) + { + //printf("color %d, pixels %d\n",x,cusage[x]); + if(cusage[x]>count) + { + count=cusage[x]; + background=x; + + } + } + + for(cy=0; cy<25; cy++) + { + //printf("\ny:%2d ",cy); + for(cx=0; cx<40; cx++) + { + numcolors=Count_used_colors_area(cusage,cx*4,cy*8,4,8); + if(numcolors>4) + { + Warning_message("More than 4 colors in 4x8"); + // TODO hilite offending block + return 1; + } + color=1; + c[0]=background; + for(i=0; i<16; i++) + { + lut[i]=0; + if(cusage[i]) + { + if(i!=background) + { + lut[i]=color; + c[color]=i; + color++; + } + else + { + lut[i]=0; + } + } + } + // add to screen and nybble + screen[cx+cy*40]=c[1]<<4|c[2]; + nybble[cx+cy*40]=c[3]; + //printf("%x%x%x ",c[1],c[2],c[3]); + for(y=0;y<8;y++) + { + bits=0; + for(x=0;x<4;x++) + { + pixel=Read_pixel_function(cx*4+x,cy*8+y); + if(pixel>15) + { + Warning_message("Color above 15 used"); + // TODO hilite as in hires, you should stay to + // the fixed 16 color palette + return 1; + } + bits=bits<<2; + bits|=lut[pixel]; + + } + Write_byte(file,bits&255); + } + } + } + Write_bytes(file,screen,1000); + Write_bytes(file,nybble,1000); + Write_byte(file,background); + //printf("\nbg:%d\n",background); + return 0; +} + +void Save_C64(void) +{ + FILE* file; + char filename[MAX_PATH_CHARACTERS]; + dword numcolors,cusage[256]; + numcolors=Count_used_colors(cusage); + + if(numcolors>16) + { + Warning_message("Error: Max 16 colors"); + File_error = 1; + return; + } + if(((Main_image_width!=320) && (Main_image_width!=160)) || Main_image_height!=200) + { + Warning_message("must be 320x200 or 160x200"); + File_error = 1; + return; + } + + Get_full_filename(filename,0); + file = fopen(filename,"wb"); + + if(!file) + { + Warning_message("File open failed"); + File_error = 1; + return; + } + + if(Main_image_width==320) + File_error = Save_C64_hires(file); + else + File_error = Save_C64_multi(file); + + fclose(file); + +} + ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //////////////////////////////////// PNG //////////////////////////////////// diff --git a/misc.c b/misc.c index ed70e042..fc6d00f9 100644 --- a/misc.c +++ b/misc.c @@ -35,696 +35,737 @@ #include "palette.h" #include "input.h" +///Count used palette indexes in the whole picture +///Return the total number of different colors +///Fill in "usage" with the count for each color word Count_used_colors(dword* usage) { - int nb_pixels=0; - Uint8* current_pixel=Main_screen; - Uint8 color; - word nb_colors=0; - int i; + int nb_pixels = 0; + Uint8* current_pixel = Main_screen; + Uint8 color; + word nb_colors = 0; + int i; - for (i=0;i<256;i++) usage[i]=0; + for (i = 0; i < 256; i++) usage[i]=0; - //Calcul du nombre de pixels dans l'image - nb_pixels=Main_image_height*Main_image_width; + // Compute total number of pixels in the picture + nb_pixels = Main_image_height * Main_image_width; - // On parcourt l'écran courant pour compter les utilisations des couleurs - for(i=0;i0;dx--) - { - // Pour chaque pixel - for(cx=width;cx>0;cx--) - { - *buffer = conversion_table[*buffer]; - buffer++; - } - buffer += buffer_width-width; - } + // Pour chaque ligne + for(dx=height;dx>0;dx--) + { + // Pour chaque pixel + for(cx=width;cx>0;cx--) + { + *buffer = conversion_table[*buffer]; + buffer++; + } + buffer += buffer_width-width; + } } void Copy_image_to_brush(short start_x,short start_y,short Brush_width,short Brush_height,word image_width) { - byte* src=start_y*image_width+start_x+Main_screen; //Adr départ image (ESI) - byte* dest=Brush; //Adr dest brosse (EDI) - int dx; + byte* src=start_y*image_width+start_x+Main_screen; //Adr départ image (ESI) + byte* dest=Brush; //Adr dest brosse (EDI) + int dx; - for (dx=Brush_height;dx!=0;dx--) - //Pour chaque ligne - { + for (dx=Brush_height;dx!=0;dx--) + //Pour chaque ligne + { - // On fait une copie de la ligne - memcpy(dest,src,Brush_width); + // On fait une copie de la ligne + memcpy(dest,src,Brush_width); - // On passe à la ligne suivante - src+=image_width; - dest+=Brush_width; - } + // On passe à la ligne suivante + src+=image_width; + dest+=Brush_width; + } } byte Read_pixel_from_feedback_screen (word x,word y) { - return *(FX_feedback_screen+y*Main_image_width+x); + return *(FX_feedback_screen+y*Main_image_width+x); } dword Round_div(dword numerator,dword divisor) { - return numerator/divisor; + return numerator/divisor; } byte Effect_sieve(word x,word y) { - return Sieve[x % Sieve_width][y % Sieve_height]; + return Sieve[x % Sieve_width][y % Sieve_height]; } void Replace_colors_within_limits(byte * replace_table) { - int line; - int counter; - byte* Adresse; + int line; + int counter; + byte* Adresse; - byte old; + byte old; - // Pour chaque ligne : - for(line = Limit_top;line <= Limit_bottom; line++) - { - // Pour chaque pixel sur la ligne : - for (counter = Limit_left;counter <= Limit_right;counter ++) - { - Adresse = Main_screen+line*Main_image_width+counter; - old=*Adresse; - *Adresse = replace_table[old]; - } - } + // Pour chaque ligne : + for(line = Limit_top;line <= Limit_bottom; line++) + { + // Pour chaque pixel sur la ligne : + for (counter = Limit_left;counter <= Limit_right;counter ++) + { + Adresse = Main_screen+line*Main_image_width+counter; + old=*Adresse; + *Adresse = replace_table[old]; + } + } } byte Read_pixel_from_backup_screen (word x,word y) { - return *(Screen_backup + x + Main_image_width * y); + return *(Screen_backup + x + Main_image_width * y); } void Palette_256_to_64(T_Palette palette) { - int i; - for(i=0;i<256;i++) - { - palette[i].R = palette[i].R >> 2; - palette[i].G = palette[i].G >> 2; - palette[i].B = palette[i].B >> 2; - } + int i; + for(i=0;i<256;i++) + { + palette[i].R = palette[i].R >> 2; + palette[i].G = palette[i].G >> 2; + palette[i].B = palette[i].B >> 2; + } } void Palette_64_to_256(T_Palette palette) { - int i; - for(i=0;i<256;i++) - { - palette[i].R = (palette[i].R << 2)|(palette[i].R >> 4); - palette[i].G = (palette[i].G << 2)|(palette[i].G >> 4); - palette[i].B = (palette[i].B << 2)|(palette[i].B >> 4); - } + int i; + for(i=0;i<256;i++) + { + palette[i].R = (palette[i].R << 2)|(palette[i].R >> 4); + palette[i].G = (palette[i].G << 2)|(palette[i].G >> 4); + palette[i].B = (palette[i].B << 2)|(palette[i].B >> 4); + } } byte Effect_interpolated_colorize (word x,word y,byte color) { - // factor_a = 256*(100-Colorize_opacity)/100 - // factor_b = 256*( Colorize_opacity)/100 - // - // (Couleur_dessous*factor_a+color*facteur_B)/256 - // + // factor_a = 256*(100-Colorize_opacity)/100 + // factor_b = 256*( Colorize_opacity)/100 + // + // (Couleur_dessous*factor_a+color*facteur_B)/256 + // - // On place dans ESI 3*Couleur_dessous ( = position de cette couleur dans la - // palette des teintes) et dans EDI, 3*color. - byte color_under = Read_pixel_from_feedback_screen(x,y); - byte blue_under=Main_palette[color_under].B; - byte blue=Main_palette[color].B; - byte green_under=Main_palette[color_under].G; - byte green=Main_palette[color].G; - byte red_under=Main_palette[color_under].R; - byte red=Main_palette[color].R; + // On place dans ESI 3*Couleur_dessous ( = position de cette couleur dans la + // palette des teintes) et dans EDI, 3*color. + byte color_under = Read_pixel_from_feedback_screen(x,y); + byte blue_under=Main_palette[color_under].B; + byte blue=Main_palette[color].B; + byte green_under=Main_palette[color_under].G; + byte green=Main_palette[color].G; + byte red_under=Main_palette[color_under].R; + byte red=Main_palette[color].R; - // On récupère les 3 composantes RVB + // On récupère les 3 composantes RVB - // blue - blue = (Factors_inv_table[blue] - + Factors_table[blue_under]) / 256; - green = (Factors_inv_table[green] - + Factors_table[green_under]) / 256; - red = (Factors_inv_table[red] - + Factors_table[red_under]) / 256; - return Best_color(red,green,blue); + // blue + blue = (Factors_inv_table[blue] + + Factors_table[blue_under]) / 256; + green = (Factors_inv_table[green] + + Factors_table[green_under]) / 256; + red = (Factors_inv_table[red] + + Factors_table[red_under]) / 256; + return Best_color(red,green,blue); } byte Effect_additive_colorize (word x,word y,byte color) { - byte color_under = Read_pixel_from_feedback_screen(x,y); - byte blue_under=Main_palette[color_under].B; - byte green_under=Main_palette[color_under].G; - byte red_under=Main_palette[color_under].R; - byte blue=Main_palette[color].B; - byte green=Main_palette[color].G; - byte red=Main_palette[color].R; + byte color_under = Read_pixel_from_feedback_screen(x,y); + byte blue_under=Main_palette[color_under].B; + byte green_under=Main_palette[color_under].G; + byte red_under=Main_palette[color_under].R; + byte blue=Main_palette[color].B; + byte green=Main_palette[color].G; + byte red=Main_palette[color].R; - return Best_color( - red>red_under?red:red_under, - green>green_under?green:green_under, - blue>blue_under?blue:blue_under); + return Best_color( + red>red_under?red:red_under, + green>green_under?green:green_under, + blue>blue_under?blue:blue_under); } byte Effect_substractive_colorize(word x,word y,byte color) { - byte color_under = Read_pixel_from_feedback_screen(x,y); - byte blue_under=Main_palette[color_under].B; - byte green_under=Main_palette[color_under].G; - byte red_under=Main_palette[color_under].R; - byte blue=Main_palette[color].B; - byte green=Main_palette[color].G; - byte red=Main_palette[color].R; + byte color_under = Read_pixel_from_feedback_screen(x,y); + byte blue_under=Main_palette[color_under].B; + byte green_under=Main_palette[color_under].G; + byte red_under=Main_palette[color_under].R; + byte blue=Main_palette[color].B; + byte green=Main_palette[color].G; + byte red=Main_palette[color].R; - return Best_color( - redTimer_start) Timer_state=1; + if((SDL_GetTicks()/55)-Timer_delay>Timer_start) Timer_state=1; } void Flip_Y_lowlevel(byte *src, short width, short height) { - // ESI pointe sur la partie haute de la brosse - // EDI sur la partie basse - byte* ESI = src ; - byte* EDI = src + (height - 1) *width; - byte tmp; - word cx; + // ESI pointe sur la partie haute de la brosse + // EDI sur la partie basse + byte* ESI = src ; + byte* EDI = src + (height - 1) *width; + byte tmp; + word cx; - while(ESI < EDI) - { - // Il faut inverser les lignes pointées par ESI et - // EDI ("Brush_width" octets en tout) + while(ESI < EDI) + { + // Il faut inverser les lignes pointées par ESI et + // EDI ("Brush_width" octets en tout) - for(cx = width;cx>0;cx--) - { - tmp = *ESI; - *ESI = *EDI; - *EDI = tmp; - ESI++; - EDI++; - } + for(cx = width;cx>0;cx--) + { + tmp = *ESI; + *ESI = *EDI; + *EDI = tmp; + ESI++; + EDI++; + } - // On change de ligne : - // ESI pointe déjà sur le début de la ligne suivante - // EDI pointe sur la fin de la ligne en cours, il - // doit pointer sur le début de la précédente... - EDI -= 2 * width; // On recule de 2 lignes - } + // On change de ligne : + // ESI pointe déjà sur le début de la ligne suivante + // EDI pointe sur la fin de la ligne en cours, il + // doit pointer sur le début de la précédente... + EDI -= 2 * width; // On recule de 2 lignes + } } void Flip_X_lowlevel(byte *src, short width, short height) { - // ESI pointe sur la partie gauche et EDI sur la partie - // droite - byte* ESI = src; - byte* EDI = src + width - 1; + // ESI pointe sur la partie gauche et EDI sur la partie + // droite + byte* ESI = src; + byte* EDI = src + width - 1; - byte* line_start; - byte* line_end; - byte tmp; - word cx; + byte* line_start; + byte* line_end; + byte tmp; + word cx; - while(ESI0;cx--) - { - tmp=*ESI; - *ESI=*EDI; - *EDI=tmp; - EDI+=width; - ESI+=width; - } + // On échange par colonnes + for(cx=height;cx>0;cx--) + { + tmp=*ESI; + *ESI=*EDI; + *EDI=tmp; + EDI+=width; + ESI+=width; + } - // On change de colonne - // ESI > colonne suivante - // EDI > colonne précédente - ESI = line_start + 1; - EDI = line_end - 1; - } + // On change de colonne + // ESI > colonne suivante + // EDI > colonne précédente + ESI = line_start + 1; + EDI = line_end - 1; + } } // Rotate a pixel buffer 180º on itself. void Rotate_180_deg_lowlevel(byte *src, short width, short height) { - // ESI pointe sur la partie supérieure de la brosse - // EDI pointe sur la partie basse - byte* ESI = src; - byte* EDI = src + height*width - 1; - // EDI pointe sur le dernier pixel de la derniere ligne - byte tmp; - word cx; + // ESI pointe sur la partie supérieure de la brosse + // EDI pointe sur la partie basse + byte* ESI = src; + byte* EDI = src + height*width - 1; + // EDI pointe sur le dernier pixel de la derniere ligne + byte tmp; + word cx; - // In case of odd height, the algorithm in this function would - // miss the middle line, so we do it this way: - if (height & 1) - { - Flip_X_lowlevel(src, width, height); - Flip_Y_lowlevel(src, width, height); - return; - } + // In case of odd height, the algorithm in this function would + // miss the middle line, so we do it this way: + if (height & 1) + { + Flip_X_lowlevel(src, width, height); + Flip_Y_lowlevel(src, width, height); + return; + } - while(ESI < EDI) - { - // On échange les deux lignes pointées par EDI et - // ESI (Brush_width octets) - // En même temps, on échange les pixels, donc EDI - // pointe sur la FIN de sa ligne + while(ESI < EDI) + { + // On échange les deux lignes pointées par EDI et + // ESI (Brush_width octets) + // En même temps, on échange les pixels, donc EDI + // pointe sur la FIN de sa ligne - for(cx=width;cx>0;cx--) - { - tmp = *ESI; - *ESI = *EDI; - *EDI = tmp; + for(cx=width;cx>0;cx--) + { + tmp = *ESI; + *ESI = *EDI; + *EDI = tmp; - EDI--; // Attention ici on recule ! - ESI++; - } - } + EDI--; // Attention ici on recule ! + ESI++; + } + } } void Rescale(byte *src_buffer, short src_width, short src_height, byte *dst_buffer, short dst_width, short dst_height, short x_flipped, short y_flipped) { - int offset,line,column; + int offset,line,column; - int x_pos_in_brush; // Position courante dans l'ancienne brosse - int y_pos_in_brush; - int delta_x_in_brush; // "Vecteur incrémental" du point précédent - int delta_y_in_brush; - int initial_x_pos; // Position X de début de parcours de ligne - - // Calcul du "vecteur incrémental": - delta_x_in_brush=(src_width<<16) * (x_flipped?-1:1) / (dst_width); - delta_y_in_brush=(src_height<<16) * (y_flipped?-1:1) / (dst_height); + int x_pos_in_brush; // Position courante dans l'ancienne brosse + int y_pos_in_brush; + int delta_x_in_brush; // "Vecteur incrémental" du point précédent + int delta_y_in_brush; + int initial_x_pos; // Position X de début de parcours de ligne - offset=0; + // Calcul du "vecteur incrémental": + delta_x_in_brush=(src_width<<16) * (x_flipped?-1:1) / (dst_width); + delta_y_in_brush=(src_height<<16) * (y_flipped?-1:1) / (dst_height); - // Calcul de la valeur initiale de y_pos: - if (y_flipped) - y_pos_in_brush=(src_height<<16)-1; // Inversion en Y de la brosse - else - y_pos_in_brush=0; // Pas d'inversion en Y de la brosse + offset=0; - // Calcul de la valeur initiale de x_pos pour chaque ligne: - if (x_flipped) - initial_x_pos = (src_width<<16)-1; // Inversion en X de la brosse - else - initial_x_pos = 0; // Pas d'inversion en X de la brosse - - // Pour chaque ligne - for (line=0;line>16) + (y_pos_in_brush>>16)*src_width); - // On passe à la colonne de brosse suivante: - x_pos_in_brush+=delta_x_in_brush; - // On passe au pixel suivant de la nouvelle brosse: - offset++; - } - // On passe à la ligne de brosse suivante: - y_pos_in_brush+=delta_y_in_brush; - } + // Calcul de la valeur initiale de x_pos pour chaque ligne: + if (x_flipped) + initial_x_pos = (src_width<<16)-1; // Inversion en X de la brosse + else + initial_x_pos = 0; // Pas d'inversion en X de la brosse + + // Pour chaque ligne + for (line=0;line>16) + (y_pos_in_brush>>16)*src_width); + // On passe à la colonne de brosse suivante: + x_pos_in_brush+=delta_x_in_brush; + // On passe au pixel suivant de la nouvelle brosse: + offset++; + } + // On passe à la ligne de brosse suivante: + y_pos_in_brush+=delta_y_in_brush; + } } void Slider_timer(byte speed) -//Boucle d'attente pour faire bouger les scrollbars à une vitesse correcte + //Boucle d'attente pour faire bouger les scrollbars à une vitesse correcte { - Uint32 end; - byte original_mouse_k = Mouse_K; - end = SDL_GetTicks() + speed*10; - do - { - if (!Get_input()) SDL_Delay(20); - } while (Mouse_K == original_mouse_k && SDL_GetTicks()0;dx--) - { - // Pour chaque ligne - memcpy(edi,esi,ax); - memcpy(edi - x_offset,esi+ax,x_offset); + byte* esi = Screen_backup; //source de la copie + byte* edi = Main_screen + y_offset * Main_image_width + x_offset; + const word ax = Main_image_width - x_offset; // Nombre de pixels à copier à droite + word dx; + for(dx = Main_image_height - y_offset;dx>0;dx--) + { + // Pour chaque ligne + memcpy(edi,esi,ax); + memcpy(edi - x_offset,esi+ax,x_offset); - // On passe à la ligne suivante - edi += Main_image_width; - esi += Main_image_width; - } + // On passe à la ligne suivante + edi += Main_image_width; + esi += Main_image_width; + } - // On vient de faire le traitement pour otutes les lignes au-dessous de y_offset - // Maintenant on traite celles au dessus - edi = x_offset + Main_screen; - for(dx = y_offset;dx>0;dx--) - { - memcpy(edi,esi,ax); - memcpy(edi - x_offset,esi+ax,x_offset); + // On vient de faire le traitement pour otutes les lignes au-dessous de y_offset + // Maintenant on traite celles au dessus + edi = x_offset + Main_screen; + for(dx = y_offset;dx>0;dx--) + { + memcpy(edi,esi,ax); + memcpy(edi - x_offset,esi+ax,x_offset); - edi += Main_image_width; - esi += Main_image_width; - } + edi += Main_image_width; + esi += Main_image_width; + } - Update_rect(0,0,0,0); + Update_rect(0,0,0,0); } void Zoom_a_line(byte* original_line, byte* zoomed_line, - word factor, word width -) + word factor, word width + ) { - byte color; - word x; + byte color; + word x; - // Pour chaque pixel - for(x=0;x +#define _WIN32_WINNT 0x0500 +#include #elif defined(__macosx__) || defined(__FreeBSD__) - #include +#include #elif defined(__BEOS__) || defined(__HAIKU__) - // sysinfo not implemented +// sysinfo not implemented #elif defined(__AROS__) || defined(__amigaos4__) || defined(__MORPHOS__) || defined(__amigaos__) - #include +#include #elif defined(__SKYOS__) - #include +#include #else - #include // sysinfo() for free RAM +#include // sysinfo() for free RAM #endif // Indique quelle est la mémoire disponible unsigned long Memory_free(void) { - // Memory is no longer relevant. If there is ANY problem or doubt here, - // you can simply return 10*1024*1024 (10Mb), to make the "Pages"something - // memory allocation functions happy. + // Memory is no longer relevant. If there is ANY problem or doubt here, + // you can simply return 10*1024*1024 (10Mb), to make the "Pages"something + // memory allocation functions happy. - // However, it is still a good idea to make a proper function if you can... - // If Grafx2 thinks the memory is full, weird things may happen. And if memory - // ever becomes full and you're still saying there are 10MB free here, the - // program will crash without saving any picture backup ! You've been warned... - #if defined(__WIN32__) - MEMORYSTATUS mstt; - mstt.dwLength = sizeof(MEMORYSTATUS); - GlobalMemoryStatus(&mstt); - return mstt.dwAvailPhys; - #elif defined(__macosx__) || defined(__FreeBSD__) - int mib[2]; - int maxmem; - size_t len; + // However, it is still a good idea to make a proper function if you can... + // If Grafx2 thinks the memory is full, weird things may happen. And if memory + // ever becomes full and you're still saying there are 10MB free here, the + // program will crash without saving any picture backup ! You've been warned... +#if defined(__WIN32__) + MEMORYSTATUS mstt; + mstt.dwLength = sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&mstt); + return mstt.dwAvailPhys; +#elif defined(__macosx__) || defined(__FreeBSD__) + int mib[2]; + int maxmem; + size_t len; - mib[0] = CTL_HW; - mib[1] = HW_USERMEM; - len = sizeof(maxmem); - sysctl(mib,2,&maxmem,&len,NULL,0); - return maxmem; - #elif defined(__BEOS__) || defined(__HAIKU__) || defined(__SKYOS__) || defined(__amigaos4__) || defined(__amigaos__) - // No on BeOS or Haiku - // AvailMem is misleading on os4 (os4 caches stuff in memory that you can still allocate) - #warning "There is missing code there for your platform ! please check and correct :)" - return 10*1024*1024; - #elif defined(__AROS__) || defined(__MORPHOS__) - return AvailMem(MEMF_ANY); - #else - struct sysinfo info; - sysinfo(&info); - return info.freeram*info.mem_unit; - #endif + mib[0] = CTL_HW; + mib[1] = HW_USERMEM; + len = sizeof(maxmem); + sysctl(mib,2,&maxmem,&len,NULL,0); + return maxmem; +#elif defined(__BEOS__) || defined(__HAIKU__) || defined(__SKYOS__) || defined(__amigaos4__) || defined(__amigaos__) + // No on BeOS or Haiku + // AvailMem is misleading on os4 (os4 caches stuff in memory that you can still allocate) +#warning "There is missing code there for your platform ! please check and correct :)" + return 10*1024*1024; +#elif defined(__AROS__) || defined(__MORPHOS__) + return AvailMem(MEMF_ANY); +#else + struct sysinfo info; + sysinfo(&info); + return info.freeram*info.mem_unit; +#endif } @@ -732,51 +773,51 @@ unsigned long Memory_free(void) // Transformer un nombre (entier naturel) en chaîne void Num2str(dword number,char * str,byte nb_char) { - int index; + int index; - for (index=nb_char-1;index>=0;index--) - { - str[index]=(number%10)+'0'; - number/=10; - if (number==0) - for (index--;index>=0;index--) - str[index]=' '; - } - str[nb_char]='\0'; + for (index=nb_char-1;index>=0;index--) + { + str[index]=(number%10)+'0'; + number/=10; + if (number==0) + for (index--;index>=0;index--) + str[index]=' '; + } + str[nb_char]='\0'; } // Arrondir un nombre réel à la valeur entière la plus proche short Round(float value) { - short temp=value; + short temp=value; - if (value>=0) - { if ((value-temp)>= 0.5) temp++; } - else - { if ((value-temp)<=-0.5) temp--; } + if (value>=0) + { if ((value-temp)>= 0.5) temp++; } + else + { if ((value-temp)<=-0.5) temp--; } - return temp; + return temp; } // Arrondir le résultat d'une division à la valeur entière supérieure short Round_div_max(short numerator,short divisor) { - if (!(numerator % divisor)) - return (numerator/divisor); - else - return (numerator/divisor)+1; + if (!(numerator % divisor)) + return (numerator/divisor); + else + return (numerator/divisor)+1; } // Retourne le minimum entre deux nombres int Min(int a,int b) { - return (ab)?a:b; + return (a>b)?a:b; } @@ -784,12 +825,12 @@ int Max(int a,int b) // Fonction retournant le libellé d'une mode (ex: " 320x200") char * Mode_label(int mode) { - static char str[24]; - if (! Video_mode[mode].Fullscreen) - return "window"; - sprintf(str, "%dx%d", Video_mode[mode].Width, Video_mode[mode].Height); + static char str[24]; + if (! Video_mode[mode].Fullscreen) + return "window"; + sprintf(str, "%dx%d", Video_mode[mode].Width, Video_mode[mode].Height); - return str; + return str; } // Trouve un mode video à partir d'une chaine: soit "window", @@ -797,12 +838,12 @@ char * Mode_label(int mode) // Renvoie -1 si la chaine n'est pas convertible int Convert_videomode_arg(const char *argument) { - // Je suis paresseux alors je vais juste tester les libellés - int mode_index; - for (mode_index=0; mode_index