From 19decb6d4ca700c524e4616fc825bd44be5f1e85 Mon Sep 17 00:00:00 2001 From: Yves Rizoud Date: Wed, 21 Oct 2009 23:00:58 +0000 Subject: [PATCH 01/30] Trunk: Restored working behavior for version and pversion git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1088 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- Makefile | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 318f5256..bc092f29 100644 --- a/Makefile +++ b/Makefile @@ -262,16 +262,12 @@ else JOYCOPT = endif -ifneq ($(PLATFORM),amiga-vbcc) - COPT += -DSVN_revision='"$(shell svnversion .)"' -DProgram_version='"$(LABEL)"' -endif - ### And now for the real build rules ### -.PHONY : all debug release clean depend zip force install uninstall +.PHONY : all debug release clean depend zip version force install uninstall # This is the list of the objects we want to build. Dependancies are built by "make depend" automatically. -OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(PLATFORMOBJ) +OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(PLATFORMOBJ) SKIN_FILES = skins/skin_classic.png skins/skin_modern.png skins/font_Classic.png skins/font_Fun.png @@ -316,6 +312,27 @@ testsed : $(BIN) : $(OBJ) $(CC) $(OBJ) -o $(BIN) $(LOPT) + +# SVN revision number +version.c : + echo "char SVN_revision[]=\"`svnversion .`\";" > version.c +ifeq ($(LABEL),) +else + echo "char Program_version[]=\"$(LABEL)\";" > pversion.c +endif + +version : delversion delpversion version.c pversion.c $(OBJDIR)/version.o $(OBJDIR)/pversion.o all + + +delversion : + $(DELCOMMAND) version.c + +delpversion : +ifeq ($(LABEL),) +else + $(DELCOMMAND) pversion.c +endif + $(OBJDIR)/%.o : %.c $(if $(wildcard $(OBJDIR)),,$(MKDIR) $(OBJDIR)) $(CC) $(COPT) -c $*.c -o $(OBJDIR)/$*.o From 111fbbcf33f4399f011aa1a320b0208a126da714 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 24 Oct 2009 13:42:59 +0000 Subject: [PATCH 02/30] -Introduce new Requester_window to ask the user to enter a single value -Reduce colors in the palette screen is now a dropdown for easy access to usual values. "Other" option opens a requester to enter a custom one if needed -Some cleanup to make things a little more readable -Build fixes after versionning system revert git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1090 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- buttons.c | 12 +-- engine.h | 32 +++++--- help.c | 3 + main.c | 2 +- palette.c | 235 ++++++++++++++++++++++++++++-------------------------- windows.c | 51 +++++++++++- windows.h | 1 + 7 files changed, 196 insertions(+), 140 deletions(-) diff --git a/buttons.c b/buttons.c index 82854e33..420a4579 100644 --- a/buttons.c +++ b/buttons.c @@ -70,7 +70,7 @@ #define isHidden(x) ((x)->d_name[0]=='.') #endif -//extern char Program_version[]; // generated in pversion.c +extern char Program_version[]; // generated in pversion.c extern short Old_MX; extern short Old_MY; @@ -793,15 +793,6 @@ void Button_Settings(void) Window_display_frame(163, 16,139,48); // Show in filelist Window_display_frame(253, 77, 49,82); // Mouse sens. Window_display_frame( 5, 65,247,96); // |_ Misc. -/* Window_display_frame( 5, 65,157,14); // | - // On découpe le Frame bizarre des "Miscellaneous" - Pixel_in_window(6,77,MC_White); - Pixel_in_window(5,78,MC_Dark); - Block(Window_pos_X+(7*Menu_factor_X),Window_pos_Y+(77*Menu_factor_Y), - Menu_factor_X*154,Menu_factor_Y<<1,MC_Light); - Pixel_in_window(161,77,MC_Light); - Pixel_in_window(160,77,MC_Dark); -*/ // On affiche maintenant tout le blabla Print_in_window(169, 19,"Show in filelist",MC_Dark,MC_Light); Print_in_window( 9, 52,"Nb of UNDO pages",MC_Dark,MC_Light); @@ -815,7 +806,6 @@ void Button_Settings(void) // Button Show/Hide dans le fileselect Window_set_normal_button(167, 28,131,14,"Hidden files: ",0,1,SDLK_LAST); // 1 Window_set_normal_button(167, 43,131,14,"Hidden dir. : ",0,1,SDLK_LAST); // 2 -// Window_set_normal_button(167, 58,131,14,"System dir. : ",0,1,SDLK_LAST); // Button Show/Hide Picture limits Window_set_normal_button( 9, 81,107,14,"Limits : ",0,1,SDLK_LAST); // 3 diff --git a/engine.h b/engine.h index e3de8d0f..94e0704a 100644 --- a/engine.h +++ b/engine.h @@ -49,33 +49,39 @@ void Window_draw_scroller_bouton(T_Scroller_button * button); void Window_input_content(T_Special_button * button, char * content); void Window_clear_input_button(T_Special_button * button); -void Window_draw_input_bouton(word x_pos,word y_pos,word width_in_characters); +void Window_draw_input_bouton(word x_pos, word y_pos, word width_in_characters); T_Normal_button * Window_set_normal_button(word x_pos, word y_pos, - word width, word height, - char * title,byte undersc_letter, - byte clickable, word shortcut); + word width, word height, char * title, byte undersc_letter, + byte clickable, word shortcut); + T_Normal_button * Window_set_repeatable_button(word x_pos, word y_pos, - word width, word height, - char * title,byte undersc_letter, - byte clickable, word shortcut); + word width, word height, char * title, byte undersc_letter, + byte clickable, word shortcut); T_Palette_button * Window_set_palette_button(word x_pos, word y_pos); void Window_clear_tags(void); -void Tag_color_range(byte start,byte end); +void Tag_color_range(byte start, byte end); T_Scroller_button * Window_set_scroller_button(word x_pos, word y_pos, word height, word nb_elements, word nb_elements_visible, word initial_position); -T_Special_button * Window_set_special_button(word x_pos,word y_pos,word width, + +T_Special_button * Window_set_special_button(word x_pos, word y_pos, word width, word height); -T_Special_button * Window_set_input_button(word x_pos,word y_pos, + +T_Special_button * Window_set_input_button(word x_pos, word y_pos, word width_in_characters); -T_Dropdown_button * Window_set_dropdown_button(word x_pos,word y_pos,word width, - word height,word dropdown_width,const char *label,byte display_choice, - byte display_centered,byte display_arrow,byte active_button); + +T_Dropdown_button * Window_set_dropdown_button(word x_pos, word y_pos, + word width, word height, word dropdown_width, const char *label, + byte display_choice, byte display_centered, byte display_arrow, + byte active_button); + +/// Adds an item to a dropdown menu void Window_dropdown_add_item(T_Dropdown_button * dropdown, word btn_number, const char *label); + void Window_dropdown_clear_items(T_Dropdown_button * dropdown); T_List_button * Window_set_list_button(T_Special_button * entry_button, T_Scroller_button * scroller, Func_draw_list_item draw_list_item); diff --git a/help.c b/help.c index f5e75e5b..53e39674 100644 --- a/help.c +++ b/help.c @@ -46,6 +46,9 @@ #include "hotkeys.h" #include "errors.h" +extern char Program_version[]; // generated in pversion.c +extern char SVN_revision[]; // generated in pversion.c + // Recherche un raccourci clavier: word * Shortcut(word shortcut_number) { diff --git a/main.c b/main.c index ecb63bb8..ba1f8aaa 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program +/* Grafx1 - The Ultimate 256-color bitmap paint program Copyright 2008 Peter Gordon Copyright 2008 Franck Charlet diff --git a/palette.c b/palette.c index 8a1abb81..0574781a 100644 --- a/palette.c +++ b/palette.c @@ -752,68 +752,81 @@ void Draw_all_palette_sliders(T_Scroller_button * red_slider, void Button_Palette(void) { - static short reducer_index=0; - static short reduce_colors_number=256; - short temp_color; // Variable pouvant reservir pour différents calculs intermédiaires - dword temp; - byte color,click; // Variables pouvant reservir pour différents calculs intermédiaires - short clicked_button; - word old_mouse_x; - word old_mouse_y; - byte old_mouse_k; - byte block_start; - byte block_end; - byte first_color; - byte last_color; - char str[10]; - word i; - //short x_pos,y_pos; + static short reduce_colors_number = 256; + short temp_color; // Variable pouvant reservir pour différents calculs intermédiaires + dword temp; + byte color,click; // Variables pouvant reservir pour différents calculs intermédiaires + short clicked_button; + word old_mouse_x; + word old_mouse_y; + byte old_mouse_k; + byte block_start; + byte block_end; + byte first_color; + byte last_color; + char str[10]; + word i; T_Normal_button * button_used; T_Scroller_button * red_slider; T_Scroller_button * green_slider; T_Scroller_button * blue_slider; - T_Scroller_button * reduce_slider; - byte image_is_backed_up=0; - byte need_to_remap=0; + T_Dropdown_button * reduce_dropdown; + byte image_is_backed_up = 0; + byte need_to_remap = 0; dword color_usage[256]; - short used_colors=-1; // -1 <=> Inconnu + short used_colors = -1; // -1 <=> Inconnu byte conversion_table[256]; T_Components * backup_palette; T_Components * temp_palette; T_Components * working_palette; - backup_palette =(T_Components *)malloc(sizeof(T_Palette)); + backup_palette =(T_Components *)malloc(sizeof(T_Palette)); temp_palette=(T_Components *)malloc(sizeof(T_Palette)); working_palette=(T_Components *)malloc(sizeof(T_Palette)); Componant_unit(RGB_scale); - Open_window(299,188,"Palette"); + Open_window(299, 188,"Palette"); - memcpy(working_palette,Main_palette,sizeof(T_Palette)); - memcpy(backup_palette ,Main_palette,sizeof(T_Palette)); - memcpy(temp_palette,Main_palette,sizeof(T_Palette)); + memcpy(working_palette, Main_palette, sizeof(T_Palette)); + memcpy(backup_palette, Main_palette, sizeof(T_Palette)); + memcpy(temp_palette, Main_palette, sizeof(T_Palette)); - Window_set_palette_button(5,79); // 1 + Window_set_palette_button(5, 79); // 1 - Window_display_frame (173, 67,121,116); - Window_display_frame (128, 16, 91, 39); - Window_display_frame (221, 16, 73, 39); - // Frame creux destiné à l'affichage de la(les) couleur(s) sélectionnée(s) - Window_display_frame_in(259, 88, 26, 74); + Window_display_frame (173, 67, 121, 116); + Window_display_frame (128, 16, 91, 39); // Graduation des jauges de couleur - Block(Window_pos_X+(Menu_factor_X*179),Window_pos_Y+(Menu_factor_Y*109),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*206),Window_pos_Y+(Menu_factor_Y*109),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*233),Window_pos_Y+(Menu_factor_Y*109),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*179),Window_pos_Y+(Menu_factor_Y*125),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*206),Window_pos_Y+(Menu_factor_Y*125),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*233),Window_pos_Y+(Menu_factor_Y*125),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*179),Window_pos_Y+(Menu_factor_Y*141),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*206),Window_pos_Y+(Menu_factor_Y*141),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*233),Window_pos_Y+(Menu_factor_Y*141),Menu_factor_X*17,Menu_factor_Y,MC_Dark); + Block(Window_pos_X + (Menu_factor_X * 179), + Window_pos_Y + (Menu_factor_Y * 109), Menu_factor_X * 17, Menu_factor_Y, + MC_Dark); + Block(Window_pos_X + (Menu_factor_X * 206), + Window_pos_Y + (Menu_factor_Y * 109), Menu_factor_X * 17, Menu_factor_Y, + MC_Dark); + Block(Window_pos_X + (Menu_factor_X * 233), + Window_pos_Y + (Menu_factor_Y * 109), Menu_factor_X * 17, Menu_factor_Y, + MC_Dark); + Block(Window_pos_X + (Menu_factor_X * 179), + Window_pos_Y + (Menu_factor_Y * 125), Menu_factor_X * 17, Menu_factor_Y, + MC_Dark); + Block(Window_pos_X + (Menu_factor_X * 206), + Window_pos_Y + (Menu_factor_Y * 125), Menu_factor_X * 17, Menu_factor_Y, + MC_Dark); + Block(Window_pos_X + (Menu_factor_X * 233), + Window_pos_Y + (Menu_factor_Y * 125), Menu_factor_X * 17, Menu_factor_Y, + MC_Dark); + Block(Window_pos_X + (Menu_factor_X * 179), + Window_pos_Y + (Menu_factor_Y * 141), Menu_factor_X * 17, Menu_factor_Y, + MC_Dark); + Block(Window_pos_X + (Menu_factor_X * 206), + Window_pos_Y + (Menu_factor_Y * 141), Menu_factor_X * 17, Menu_factor_Y, + MC_Dark); + Block(Window_pos_X + (Menu_factor_X * 233), + Window_pos_Y + (Menu_factor_Y * 141), Menu_factor_X * 17, Menu_factor_Y, + MC_Dark); // Jauges de couleur red_slider = Window_set_scroller_button(182, 81, 88,Color_count,1,Color_max-working_palette[Fore_color].R*Color_max/255);// 2 green_slider = Window_set_scroller_button(209, 81, 88,Color_count,1,Color_max-working_palette[Fore_color].G*Color_max/255);// 3 @@ -853,8 +866,16 @@ void Button_Palette(void) Window_set_normal_button(66,32,29,14,"Cpy" ,1,1,SDLK_c); // 9 Window_set_normal_button( 6,32,59,14,"Spread" ,4,1,SDLK_e); // 10 - Window_set_normal_button(239,20,51,14,"Reduce" ,1,1,SDLK_r); // 11 - Print_in_window(241,41,"to",MC_Dark,MC_Light); + reduce_dropdown = Window_set_dropdown_button(222, 18, 60, 14, 60, "Reduce", 0, + 0, 1, 1); // 11 + Window_dropdown_add_item(reduce_dropdown, 0, "to 128"); + Window_dropdown_add_item(reduce_dropdown, 1, "to 64"); + Window_dropdown_add_item(reduce_dropdown, 2, "to 32"); + Window_dropdown_add_item(reduce_dropdown, 3, "to 16"); + Window_dropdown_add_item(reduce_dropdown, 4, "to 8"); + Window_dropdown_add_item(reduce_dropdown, 5, "to 4"); + Window_dropdown_add_item(reduce_dropdown, 6, "to 2"); + Window_dropdown_add_item(reduce_dropdown, 7, "Other"); Window_set_normal_button( 6,168,35,14,"Undo" ,1,1,SDLK_u); // 12 Window_set_normal_button( 62,168,51,14,"Cancel",0,1,KEY_ESC); // 13 @@ -863,23 +884,15 @@ void Button_Palette(void) button_used = Window_set_normal_button(132,20,83,14,"Used: ???",4,1,SDLK_d);// 15 Window_set_normal_button(132,37,83,14,"Zap unused",0,1,SDLK_DELETE);//16 - // Jauge de réduction de palette - reduce_slider = Window_set_scroller_button(225,20,31,7,1,reducer_index);// 17 + Window_set_repeatable_button(266, 74,12,11,"+",0,1,SDLK_KP_PLUS); // 17 + Window_set_repeatable_button(266,165,12,11,"-",0,1,SDLK_KP_MINUS); // 18 - Window_set_repeatable_button(266, 74,12,11,"+",0,1,SDLK_KP_PLUS); // 18 - Window_set_repeatable_button(266,165,12,11,"-",0,1,SDLK_KP_MINUS); // 19 + Window_set_normal_button(96,17,29,14,"Neg" ,1,1,SDLK_n); // 19 + Window_set_normal_button(66,62,29,14,"Inv" ,1,1,SDLK_i); // 20 + Window_set_normal_button( 6,62,59,14,"X-Inv." ,5,1,SDLK_v); // 21 - Window_set_normal_button(96,17,29,14,"Neg" ,1,1,SDLK_n); // 20 - Window_set_normal_button(66,62,29,14,"Inv" ,1,1,SDLK_i); // 21 - Window_set_normal_button( 6,62,59,14,"X-Inv." ,5,1,SDLK_v); // 22 - - Window_set_input_button(263,39,3); // 23 - - Window_set_normal_button(96,32,29,14,"HSL" ,1,1,SDLK_h); // 24 - Window_set_normal_button(96,47,29,14,"Srt" ,1,1,SDLK_s); // 25 - // Affichage du facteur de réduction de la palette - Num2str(reduce_colors_number,str,3); - Print_in_window(265,41,str,MC_Black,MC_Light); + Window_set_normal_button(96,32,29,14,"HSL" ,1,1,SDLK_h); // 22 + Window_set_normal_button(96,47,29,14,"Srt" ,1,1,SDLK_s); // 23 // Dessin des petits effets spéciaux pour les boutons [+] et [-] Draw_thingumajig(263, 74,MC_White,-1); @@ -1400,29 +1413,64 @@ void Button_Palette(void) break; case 11: // Reduce - memcpy(backup_palette,working_palette,sizeof(T_Palette)); + memcpy(backup_palette, working_palette, sizeof(T_Palette)); + switch(Window_attribute2) // Get the dropdown value + { + case 0: // 128 + reduce_colors_number = 128; + break; + case 1: // 64 + reduce_colors_number = 64; + break; + case 2: // 32 + reduce_colors_number = 32; + break; + case 3: // 16 + reduce_colors_number = 16; + break; + case 4: // 8 + reduce_colors_number = 8; + break; + case 5: // 4 + reduce_colors_number = 4; + break; + case 6: // 2 + reduce_colors_number = 2; + break; + case 7: // other + reduce_colors_number + = Requester_window("Enter the max. number of colors", + reduce_colors_number); + if (reduce_colors_number < 2 || reduce_colors_number > 256) + reduce_colors_number = 256; + break; + } + if (!image_is_backed_up) { Backup(); - image_is_backed_up=1; + image_is_backed_up = 1; } - Reduce_palette(&used_colors,reduce_colors_number,working_palette,color_usage); + + Reduce_palette(&used_colors, reduce_colors_number, working_palette, + color_usage); if ((Config.Safety_colors) && (used_colors<4)) { - memcpy(temp_palette,Main_palette,sizeof(T_Palette)); - memcpy(Main_palette,working_palette,sizeof(T_Palette)); - Set_nice_menu_colors(color_usage,0); - memcpy(working_palette,Main_palette,sizeof(T_Palette)); - memcpy(Main_palette,temp_palette,sizeof(T_Palette)); + memcpy(temp_palette, Main_palette, sizeof(T_Palette)); + memcpy(Main_palette, working_palette, sizeof(T_Palette)); + Set_nice_menu_colors(color_usage, 0); + memcpy(working_palette, Main_palette, sizeof(T_Palette)); + memcpy(Main_palette, temp_palette, sizeof(T_Palette)); } - Set_palette(working_palette); // On définit la nouvelle palette - Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); - memcpy(temp_palette,working_palette,sizeof(T_Palette)); + Set_palette(working_palette); // On définit la nouvelle palette + Draw_all_palette_sliders(red_slider, green_slider, blue_slider, + working_palette, block_start, block_end); + memcpy(temp_palette, working_palette, sizeof(T_Palette)); End_of_modification(); - need_to_remap=1; + need_to_remap = 1; break; case 12: // Undo @@ -1470,19 +1518,7 @@ void Button_Palette(void) need_to_remap=1; break; - case 17 : // Jauge de réduction de palette - if (reducer_index!=reduce_slider->Position) - { - reducer_index=reduce_slider->Position; - // Affichage du facteur de réduction de la palette - Hide_cursor(); - Print_in_window(265,41,Palette_reduce_label[reducer_index],MC_Black,MC_Light); - Display_cursor(); - reduce_colors_number=atoi(Palette_reduce_label[reducer_index]); - } - break; - - case 18 : // [+] + case 17 : // [+] if (!Palette_view_is_RGB) break; Hide_cursor(); @@ -1607,7 +1643,7 @@ void Button_Palette(void) Set_palette(working_palette); break; - case 19 : // [-] + case 18 : // [-] if (!Palette_view_is_RGB) break; Hide_cursor(); @@ -1732,7 +1768,7 @@ void Button_Palette(void) Set_palette(working_palette); break; - case 20 : // Negative + case 19 : // Negative // Backup memcpy(backup_palette,working_palette,sizeof(T_Palette)); // Negative @@ -1750,8 +1786,8 @@ void Button_Palette(void) need_to_remap=1; break; - case 21 : // Inversion - case 22 : // X-Inversion + case 20 : // Inversion + case 21 : // X-Inversion // Backup memcpy(backup_palette,working_palette,sizeof(T_Palette)); // On initialise la table de conversion @@ -1795,30 +1831,7 @@ void Button_Palette(void) need_to_remap=1; break; - case 23 : // Saisie du nombre de couleurs pour la réduction de palette - Num2str(reduce_colors_number,str,3); - - if (Readline(265,41,str,3,1)) - { - temp_color=atoi(str); - // Correction de la valeur lue - if ( (temp_color>256) || (temp_color<2) ) - { - if (temp_color>256) - temp_color=256; - else - temp_color=2; - - Num2str(temp_color,str,3); - Window_input_content(Window_special_button_list,str); - } - - reduce_colors_number=temp_color; - } - Display_cursor(); - break; - - case 24 : // HSL <> RGB + case 22 : // HSL <> RGB // Acte les changements en cours sur une ou plusieurs couleurs memcpy(temp_palette,working_palette,sizeof(T_Palette)); @@ -1854,7 +1867,7 @@ void Button_Palette(void) Update_window_area(265,73,14,103); break; - case 25 : // Sort palette + case 23 : // Sort palette { byte h = 0, l = 0, s=0; byte oh=0,ol=0,os=0; // Valeur pour la couleur précédente diff --git a/windows.c b/windows.c index a22377e1..52b3b1a9 100644 --- a/windows.c +++ b/windows.c @@ -26,13 +26,15 @@ #include // strncpy() strlen() #include "windows.h" + +#include "engine.h" +#include "errors.h" #include "global.h" #include "graph.h" -#include "engine.h" -#include "misc.h" -#include "sdlscreen.h" -#include "errors.h" #include "input.h" +#include "misc.h" +#include "readline.h" +#include "sdlscreen.h" // L'encapsulation tente une percée...ou un dernier combat. @@ -836,6 +838,47 @@ byte Confirmation_box(char * message) } +/// Window that allows you to enter a single value +int Requester_window(char* message, int initial_value) +{ + short clicked_button = 0; + word window_width; + char str[10]; + + window_width=(strlen(message)<<3)+20; + + if (window_width<120) + window_width = 120; + + Open_window(window_width, 60, "Request"); + + Print_in_window((window_width>>1)-(strlen(message)<<2), 20, message, + MC_Black, MC_Light); + sprintf(str, "%d", initial_value); + Window_set_input_button((window_width / 3) - 20, 37, 10); // 1 + Print_in_window((window_width / 3) - 18, 39, str, MC_Black, MC_Light); + + Update_rect(Window_pos_X, Window_pos_Y, Menu_factor_X * window_width, + Menu_factor_Y * 60); + Display_cursor(); + + do + { + clicked_button = Window_clicked_button(); + if (clicked_button == 1) + Readline((window_width / 3) - 18, 39, str, 10, 1); + if (Key == SDLK_ESCAPE) clicked_button = 2; + } + while (clicked_button <= 0); + + Key = 0; + + Close_window(); + Display_cursor(); + + return clicked_button==2?-1:atoi(str); +} + /// Window that show a warning message and wait for a click on the OK button void Warning_message(char * message) diff --git a/windows.h b/windows.h index 7feff36f..d87b3bb6 100644 --- a/windows.h +++ b/windows.h @@ -71,6 +71,7 @@ void Print_counter(short x,short y,const char * str,byte text_color,byte backgro byte Confirmation_box(char * message); void Warning_message(char * message); void Verbose_error_message(char * message); +int Requester_window(char* message, int initial_value); void Display_image_limits(void); void Display_all_screen(void); From 42ac69177fdd9a9b5d5b47120484a86974265457 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 24 Oct 2009 14:06:12 +0000 Subject: [PATCH 03/30] Added a color counter to the palette screen. It needs the setting to autocount colors to be enabled and probably display garbage when it's disabled. Is this setting really useful ? Do someone dsable it ? git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1091 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- palette.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/palette.c b/palette.c index 0574781a..38a33637 100644 --- a/palette.c +++ b/palette.c @@ -854,10 +854,9 @@ void Button_Palette(void) // Affichage des valeurs de la couleur courante (pour 1 couleur) Display_sliders(red_slider,green_slider,blue_slider,(block_start!=block_end),working_palette); - Print_in_window(129,58,"Color number:",MC_Dark,MC_Light); - Num2str(Fore_color,str,3); - Print_in_window(237,58,str,MC_Black,MC_Light); - + Print_in_window(129, 58, "Color number:", MC_Dark, MC_Light); + Num2str(Fore_color, str, 3); + Print_in_window(237, 58, str, MC_Black, MC_Light); Window_set_normal_button( 6,17,59,14,"Default",3,1,SDLK_f); // 5 Window_set_normal_button(66,17,29,14,"Gry" ,1,1,SDLK_g); // 6 @@ -866,7 +865,7 @@ void Button_Palette(void) Window_set_normal_button(66,32,29,14,"Cpy" ,1,1,SDLK_c); // 9 Window_set_normal_button( 6,32,59,14,"Spread" ,4,1,SDLK_e); // 10 - reduce_dropdown = Window_set_dropdown_button(222, 18, 60, 14, 60, "Reduce", 0, + reduce_dropdown = Window_set_dropdown_button(222, 17, 60, 14, 60, "Reduce", 0, 0, 1, 1); // 11 Window_dropdown_add_item(reduce_dropdown, 0, "to 128"); Window_dropdown_add_item(reduce_dropdown, 1, "to 64"); @@ -894,6 +893,17 @@ void Button_Palette(void) Window_set_normal_button(96,32,29,14,"HSL" ,1,1,SDLK_h); // 22 Window_set_normal_button(96,47,29,14,"Srt" ,1,1,SDLK_s); // 23 + if (Config.Auto_nb_used) + { + Update_color_count(&used_colors,color_usage); + + Num2str(color_usage[Fore_color], str, 6); + Print_in_window(222, 33, str, MC_Black, MC_Light); + Print_in_window(222, 42, "pixels", MC_Dark, MC_Light); + } + + + // Dessin des petits effets spéciaux pour les boutons [+] et [-] Draw_thingumajig(263, 74,MC_White,-1); Draw_thingumajig(280, 74,MC_White,+1); @@ -904,9 +914,6 @@ void Button_Palette(void) Display_cursor(); - if (Config.Auto_nb_used) - Update_color_count(&used_colors,color_usage); - do { old_mouse_x=Mouse_X; @@ -955,6 +962,8 @@ void Button_Palette(void) Block(Window_pos_X+(Menu_factor_X*237),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*56,Menu_factor_Y*7,MC_Light); Num2str(Fore_color,str,3); Print_in_window(237,58,str,MC_Black,MC_Light); + Num2str(color_usage[Fore_color], str, 6); + Print_in_window(222, 33, str, MC_Black, MC_Light); Update_rect(Window_pos_X+(Menu_factor_X*237),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*56,Menu_factor_Y*7); // Affichage des jauges @@ -985,6 +994,13 @@ void Button_Palette(void) Num2str(block_end ,str+4,3); str[3]=26; // Flèche vers la droite Print_in_window(237,58,str,MC_Black,MC_Light); + { + int pixel_count = 0; + for (i = block_start; i <= block_end; i++) + pixel_count += color_usage[i]; + Num2str(pixel_count, str, 6); + } + Print_in_window(222, 33, str, MC_Black, MC_Light); // Affichage des jauges Display_sliders(red_slider,green_slider,blue_slider,1,NULL); @@ -1002,6 +1018,13 @@ void Button_Palette(void) Num2str(block_end ,str+4,3); str[3]=26; // Flèche vers la droite Print_in_window(237,58,str,MC_Black,MC_Light); + { + int pixel_count = 0; + for (i = block_start; i <= block_end; i++) + pixel_count += color_usage[i]; + Num2str(pixel_count, str, 6); + } + Print_in_window(222, 33, str, MC_Black, MC_Light); // Affichage des jauges Display_sliders(red_slider,green_slider,blue_slider,1,NULL); @@ -1018,6 +1041,8 @@ void Button_Palette(void) Block(Window_pos_X+(Menu_factor_X*261),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*32,Menu_factor_Y*7,MC_Light); Num2str(Fore_color,str,3); Print_in_window(237,58,str,MC_Black,MC_Light); + Num2str(Fore_color, str, 6); + Print_in_window(222, 33, str, MC_Black, MC_Light); // Affichage des jauges Display_sliders(red_slider,green_slider,blue_slider,0,working_palette); @@ -2041,7 +2066,7 @@ void Button_Palette(void) image_is_backed_up=1; } if (used_colors==-1) - Update_color_count(&used_colors,color_usage); + Update_color_count(&used_colors, color_usage); memcpy(backup_palette,working_palette,sizeof(T_Palette)); memcpy(temp_palette,Main_palette,sizeof(T_Palette)); From 54a673f10f8be8f901cff451f84b178262279c8e Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 25 Oct 2009 14:36:49 +0000 Subject: [PATCH 04/30] Fixed some warnings spotted by vbcc on amiga. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1092 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- windows.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/windows.c b/windows.c index 52b3b1a9..43c87e01 100644 --- a/windows.c +++ b/windows.c @@ -23,6 +23,7 @@ */ #include +#include // atoi() #include // strncpy() strlen() #include "windows.h" @@ -1163,7 +1164,7 @@ void Display_menu_palette_avoiding_window(byte * table) if (table[real_color]!=real_color) { start_x=Palette_cell_X(real_color); - start_y=Palette_cell_Y(real_color); //Menu_Y_before_window ??! + start_y=Palette_cell_Y(real_color); end_x=start_x+width; end_y=start_y+height; From 4d20be005375ddd681fff9111e73da9e1c642ddf Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Tue, 27 Oct 2009 10:28:32 +0000 Subject: [PATCH 05/30] Fixed some more amiga vbcc warnings git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1093 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- loadsave.c | 17 +++++++++-------- misc.c | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/loadsave.c b/loadsave.c index 8f3c31de..f24818d4 100644 --- a/loadsave.c +++ b/loadsave.c @@ -31,6 +31,7 @@ #include #endif #include +#include #include "buttons.h" #include "const.h" @@ -828,7 +829,7 @@ void Load_PAL(void) if ((file=fopen(filename, "rb"))) { T_Palette palette_64; - // Init_preview(???); // Pas possible... pas d'image... + // Init_preview(?); // Pas possible... pas d'image... // Lecture du fichier dans Main_palette if (Read_bytes(file,palette_64,sizeof(T_Palette))) @@ -4551,10 +4552,10 @@ void Save_CEL(void) memcpy(header2.Signature,"KiSS",4); // Initialisation de la signature header2.Kind=0x20; // Initialisation du type (BitMaP) header2.Nb_bits=8; // Initialisation du nombre de bits - header2.Filler1=0; // Initialisation du filler 1 (???) + header2.Filler1=0; // Initialisation du filler 1 (?) header2.Width=Main_image_width-header2.X_offset; // Initialisation de la largeur header2.Height=Main_image_height-header2.Y_offset; // Initialisation de la hauteur - for (x_pos=0;x_pos<16;x_pos++) // Initialisation du filler 2 (???) + for (x_pos=0;x_pos<16;x_pos++) // Initialisation du filler 2 (?) header2.Filler2[x_pos]=0; if (Write_bytes(file,&header2,sizeof(T_CEL_Header2))) @@ -4670,7 +4671,7 @@ void Load_KCF(void) if (Read_bytes(file,&buffer,sizeof(T_KCF_Header))) { - // Init_preview(???); // Pas possible... pas d'image... + // Init_preview(?); // Pas possible... pas d'image... if (Config.Clear_palette) memset(Main_palette,0,sizeof(T_Palette)); @@ -4704,7 +4705,7 @@ void Load_KCF(void) if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) { - // Init_preview(???); // Pas possible... pas d'image... + // Init_preview(?); // Pas possible... pas d'image... index=(header2.Nb_bits==12)?16:0; for (pal_index=0;pal_index 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__) +#elif defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) return AvailMem(MEMF_ANY); #else struct sysinfo info; From 193442597266e65a860f409b94f55d38ad7d1ee2 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 29 Oct 2009 15:22:45 +0000 Subject: [PATCH 06/30] Added "Brush Factory", allowing you to run a lua script to generate (or alter, untested yet) a brush. Added a simple (and ugly) sample script. This needs updates to the makefile for platforms other than linux. TODO: add a listbox to select the script you want to run. Do we have a simple API to handle filelists yet ? git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1094 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- Makefile | 17 +++++-- brush.h | 2 + buttons.h | 16 +++--- engine.c | 4 ++ engine.h | 2 +- factory.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ factory.h | 1 + init.c | 41 ++++++++------- main.c | 2 +- misc.c | 6 +-- windows.c | 2 +- windows.h | 2 +- 12 files changed, 208 insertions(+), 35 deletions(-) create mode 100644 factory.c create mode 100644 factory.h diff --git a/Makefile b/Makefile index bc092f29..3397ccf4 100644 --- a/Makefile +++ b/Makefile @@ -227,8 +227,8 @@ else # Compiles a regular linux exectutable for the native platform BIN = grafx2 - COPT = -W -Wall -Wdeclaration-after-statement -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT) - LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng + COPT = -W -Wall -Wdeclaration-after-statement -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT) $(LUACOPT) + LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng $(LUALOPT) # Use gcc for compiling. Use ncc to build a callgraph and analyze the code. CC = gcc #CC = nccgen -ncgcc -ncld -ncfabs @@ -253,6 +253,17 @@ else TTFLABEL = endif +#Lua scripting is optional too +ifeq ($(NOLUA),1) + LUACOPT = + LUALOPT = + LUALABEL = -nolua +else + LUACOPT = -D__ENABLE_LUA__ + LUALOPT = -llua5.1 + LUALABEL = +endif + #To disable Joystick emulation of cursor, make NOJOY=1 (for input.o) #This can be necessary to test keyboard cursor code, because an existing #joystick will keep reporting a contradicting position. @@ -267,7 +278,7 @@ endif .PHONY : all debug release clean depend zip version force install uninstall # This is the list of the objects we want to build. Dependancies are built by "make depend" automatically. -OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(PLATFORMOBJ) +OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) SKIN_FILES = skins/skin_classic.png skins/skin_modern.png skins/font_Classic.png skins/font_Fun.png diff --git a/brush.h b/brush.h index 437c43cc..f7e20080 100644 --- a/brush.h +++ b/brush.h @@ -25,6 +25,8 @@ #ifndef __BRUSH_H_ #define __BRUSH_H_ +#include "struct.h" + /*! Gets the brush from the picture. @param start_x left edge coordinate in the picture diff --git a/buttons.h b/buttons.h index 65db64a1..4088f0a5 100644 --- a/buttons.h +++ b/buttons.h @@ -17,10 +17,10 @@ along with Grafx2; if not, see */ -////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// ///@file buttons.h /// Almost all the editor actions that are called by the menu are here. -////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// #ifndef __BOUTONS_H_ #define __BOUTONS_H_ @@ -28,19 +28,21 @@ #include "struct.h" /*! - Displays an error message when there is no more memory for the requested operation. + Displays an error message when there is no more memory for the requested + operation. */ void Message_out_of_memory(void); /*! - Displays the splash screen at program startup. + Displays the splash screen at program startup. */ void Button_Message_initial(void); /*! - Changes brush shape. - This function saves the current brush shape and swith to the default one (single pixel brush) for the filler and the color picker. - These functions don't need (and will not work with) a custom brush. + Changes brush shape. + This function saves the current brush shape and swith to the default one + (single pixel brush) for the filler and the color picker. + These functions don't need (and will not work with) a custom brush. */ void Change_paintbrush_shape(byte shape); diff --git a/engine.c b/engine.c index 80a49c94..63c86154 100644 --- a/engine.c +++ b/engine.c @@ -79,7 +79,11 @@ char * Menu_tooltip[NB_BUTTONS]= "Grad. spheres / ellipses", "Brush grab. / Restore ", "Lasso / Restore brush ", +#ifdef __ENABLE_LUA__ + "Brush effects / factory ", +#else "Brush effects ", +#endif "Drawing modes (effects) ", "Text ", "Magnify mode / Menu ", diff --git a/engine.h b/engine.h index 94e0704a..14b84244 100644 --- a/engine.h +++ b/engine.h @@ -86,7 +86,7 @@ void Window_dropdown_clear_items(T_Dropdown_button * dropdown); T_List_button * Window_set_list_button(T_Special_button * entry_button, T_Scroller_button * scroller, Func_draw_list_item draw_list_item); void Window_redraw_list(T_List_button * list); -byte Window_click_in_rectangle(short start_x,short start_y,short end_x, +byte Window_click_in_rectangle(short start_x, short start_y, short end_x, short end_y); short Wait_click_in_palette(T_Palette_button * button); void Get_color_behind_window(byte * color, byte * click); diff --git a/factory.c b/factory.c new file mode 100644 index 00000000..5eb20489 --- /dev/null +++ b/factory.c @@ -0,0 +1,148 @@ +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2009 Adrien Destugues + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +/*! \file factory.c + * \brief Brush factory - generates brush from lua scripts + * + * The brush factory allows you to generate brushes with Lua code. + */ + +#include "brush.h" +#include "buttons.h" +#include "engine.h" +#include "global.h" +#include "misc.h" +#include "readline.h" +#include "sdlscreen.h" +#include "windows.h" + +#ifdef __ENABLE_LUA__ + +#include +#include + +// Wrapper functions to call C from Lua +int L_PutPixel(lua_State* L) +{ + Pixel_in_brush(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tonumber(L, 3)); + return 0; // no values returned for lua +} + +int L_GetPixel(lua_State* L) +{ + uint8_t c = Read_pixel_from_brush(lua_tonumber(L, 1), lua_tonumber(L, 2)); + lua_pushinteger(L, c); + return 1; +} + +void Button_Brush_Factory(void) +{ + short clicked_button; + word height; + word width; + char str[5]; + + T_Special_button* width_button; + T_Special_button* height_button; + + Open_window(154, 162, "Brush Factory"); + + Window_set_normal_button(77, 141, 67, 14, "Cancel", 0, 1, KEY_ESC); // 1 + Window_set_normal_button(10, 141, 67, 14, "Run", 0, 1, 0); // 2 + Print_in_window(10, 17, "Width:", MC_Black, MC_Light); + width_button = Window_set_input_button(64, 15, 4); // 3 + Print_in_window(10, 30, "Height:", MC_Black, MC_Light); + height_button = Window_set_input_button(64, 28, 4); // 4 + + width = Paintbrush_width; + Num2str(width, str, 4); + Window_input_content(width_button, str); + + height = Paintbrush_height; + Num2str(height, str, 4); + Window_input_content(height_button, str); + + Update_window_area(0, 0, Window_width, Window_height); + Display_cursor(); + + do { + clicked_button = Window_clicked_button(); + + switch (clicked_button) + { + case 3 : // Largeur + Num2str(width, str, 4); + Readline(65, 16, str, 4, 1); + width = atoi(str); + // On corrige les dimensions + if (width == 0) + { + width = 1; + Num2str(width, str, 4); + Window_input_content(width_button, str); + } + Display_cursor(); + break; + + case 4 : // Height + Num2str(height, str, 4); + Readline(65, 29, str, 4, 1); + height = atoi(str); + // On corrige les dimensions + if (height == 0) + { + height = 1; + Num2str(height, str, 4); + Window_input_content(height_button, str); + } + Display_cursor(); + break; + + default: + break; + } + + } while (clicked_button <= 0 || clicked_button >= 3); + + if (clicked_button == 2) // Run the script + { + lua_State* L = lua_open(); + + Realloc_brush(width, height); + + lua_register(L,"putpixel",L_PutPixel); + lua_register(L,"getpixel",L_GetPixel); + + if (luaL_loadfile(L,"./test.lua") != 0) + Verbose_error_message(lua_tostring(L, 1)); + + lua_pushinteger(L, width); + lua_pushinteger(L, height); + if (lua_pcall(L, 2, 0, 0) != 0) + Verbose_error_message(lua_tostring(L, 1)); + + lua_close(L); + + Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH); + } + + Close_window(); + Display_cursor(); +} + +#endif diff --git a/factory.h b/factory.h new file mode 100644 index 00000000..cefd687c --- /dev/null +++ b/factory.h @@ -0,0 +1 @@ +void Button_Brush_Factory(void); diff --git a/init.c b/init.c index 5ea4596c..63fe3f31 100644 --- a/init.c +++ b/init.c @@ -48,26 +48,27 @@ #include #endif +#include "buttons.h" #include "const.h" -#include "struct.h" +#include "errors.h" #include "global.h" #include "graph.h" -#include "buttons.h" -#include "palette.h" -#include "help.h" -#include "operatio.h" -#include "misc.h" -#include "errors.h" -#include "keyboard.h" -#include "io.h" -#include "hotkeys.h" -#include "setup.h" -#include "windows.h" -#include "sdlscreen.h" -#include "mountlist.h" // read_file_system_list -#include "loadsave.h" // Image_emergency_backup #include "init.h" +#include "io.h" +#include "factory.h" +#include "help.h" +#include "hotkeys.h" +#include "keyboard.h" +#include "loadsave.h" // Image_emergency_backup +#include "misc.h" +#include "mountlist.h" // read_file_system_list +#include "operatio.h" +#include "palette.h" +#include "sdlscreen.h" +#include "setup.h" +#include "struct.h" #include "transform.h" +#include "windows.h" char Gui_loading_error_message[512]; @@ -1058,10 +1059,14 @@ void Init_buttons(void) FAMILY_INTERRUPTION); Init_button(BUTTON_BRUSH_EFFECTS, - 106,18, - 16,16, + 106, 18, + 16, 16, BUTTON_SHAPE_RECTANGLE, - Button_Brush_FX,Button_Brush_FX, +#ifdef __ENABLE_LUA__ + Button_Brush_FX, Button_Brush_Factory, +#else + Button_Brush_FX, Button_Brush_FX, +#endif Do_nothing, FAMILY_INSTANT); diff --git a/main.c b/main.c index ba1f8aaa..ecb63bb8 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* Grafx1 - The Ultimate 256-color bitmap paint program +/* Grafx2 - The Ultimate 256-color bitmap paint program Copyright 2008 Peter Gordon Copyright 2008 Franck Charlet diff --git a/misc.c b/misc.c index d2911d1f..3d2c4679 100644 --- a/misc.c +++ b/misc.c @@ -206,12 +206,12 @@ void Init_chrono(dword delay) return; } -void Pixel_in_brush (word x,word y,byte color) +void Pixel_in_brush (word x, word y, byte color) { - *(Brush+y*Brush_width+x)=color; + *(Brush + y * Brush_width + x)=color; } -byte Read_pixel_from_brush (word x,word y) +byte Read_pixel_from_brush (word x, word y) { return *(Brush + y * Brush_width + x); } diff --git a/windows.c b/windows.c index 43c87e01..e6da7849 100644 --- a/windows.c +++ b/windows.c @@ -908,7 +908,7 @@ void Warning_message(char * message) } /// Window that shows a big message, and waits for a click on OK -void Verbose_error_message(char * message) +void Verbose_error_message(const char * message) { short clicked_button; int line; diff --git a/windows.h b/windows.h index d87b3bb6..a612807f 100644 --- a/windows.h +++ b/windows.h @@ -70,7 +70,7 @@ void Print_counter(short x,short y,const char * str,byte text_color,byte backgro byte Confirmation_box(char * message); void Warning_message(char * message); -void Verbose_error_message(char * message); +void Verbose_error_message(const char * message); int Requester_window(char* message, int initial_value); void Display_image_limits(void); From 06892015eaaef0a7ff73b7d8b4eb42d69b13c503 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 29 Oct 2009 15:52:21 +0000 Subject: [PATCH 07/30] added lua binding to set a color in the palette git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1097 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- factory.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/factory.c b/factory.c index 5eb20489..79b53850 100644 --- a/factory.c +++ b/factory.c @@ -50,6 +50,13 @@ int L_GetPixel(lua_State* L) return 1; } +int L_SetColor(lua_State* L) +{ + Set_color(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tonumber(L, 3), + lua_tonumber(L, 4)); + return 0; +} + void Button_Brush_Factory(void) { short clicked_button; @@ -127,6 +134,7 @@ void Button_Brush_Factory(void) lua_register(L,"putpixel",L_PutPixel); lua_register(L,"getpixel",L_GetPixel); + lua_register(L,"setcolor",L_SetColor); if (luaL_loadfile(L,"./test.lua") != 0) Verbose_error_message(lua_tostring(L, 1)); From 2a67c9bdce378241102c3c3f0b5f8edc2bb2dc2b Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 29 Oct 2009 17:27:49 +0000 Subject: [PATCH 08/30] Refactored (yes, already) the lua API to allow also generating pictures directly. Updated doc, and added sample script. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1099 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- errors.h | 2 +- factory.c | 117 +++++++++++++++++++++++++++--------------------------- test.lua | 7 ++++ 3 files changed, 67 insertions(+), 59 deletions(-) create mode 100644 test.lua diff --git a/errors.h b/errors.h index cade3071..4f1cab97 100644 --- a/errors.h +++ b/errors.h @@ -21,7 +21,7 @@ /// Functions and macros for tracing and error reporting. ////////////////////////////////////////////////////////////////////////////// -#ifndef __func__ +#ifdef __VBCC__ #define __func__ "stupid compiler !" #endif diff --git a/factory.c b/factory.c index 79b53850..89991563 100644 --- a/factory.c +++ b/factory.c @@ -25,7 +25,9 @@ #include "brush.h" #include "buttons.h" #include "engine.h" +#include "errors.h" #include "global.h" +#include "graph.h" #include "misc.h" #include "readline.h" #include "sdlscreen.h" @@ -37,19 +39,62 @@ #include // Wrapper functions to call C from Lua -int L_PutPixel(lua_State* L) + +int L_SetBrushSize(lua_State* L) +{ + Realloc_brush(lua_tonumber(L, 1), lua_tonumber(L, 2)); + return 0; +} + +int L_GetBrushSize(lua_State* L) +{ + DEBUG("GBS",Brush_width); + lua_pushinteger(L, Brush_width); + lua_pushinteger(L, Brush_height); + return 2; +} + +int L_PutBrushPixel(lua_State* L) { Pixel_in_brush(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tonumber(L, 3)); return 0; // no values returned for lua } -int L_GetPixel(lua_State* L) +int L_GetBrushPixel(lua_State* L) { uint8_t c = Read_pixel_from_brush(lua_tonumber(L, 1), lua_tonumber(L, 2)); lua_pushinteger(L, c); return 1; } +int L_SetPictureSize(lua_State* L) +{ + Resize_image(lua_tonumber(L, 1), lua_tonumber(L, 2)); + return 0; +} + +int L_GetPictureSize(lua_State* L) +{ + lua_pushinteger(L, Main_image_width); + lua_pushinteger(L, Main_image_height); + return 2; +} + +int L_PutPicturePixel(lua_State* L) +{ + Pixel_in_current_screen(lua_tonumber(L, 1), lua_tonumber(L, 2), + lua_tonumber(L, 3)); + return 0; // no values returned for lua +} + +int L_GetPicturePixel(lua_State* L) +{ + uint8_t c = Read_pixel_from_current_screen(lua_tonumber(L, 1), + lua_tonumber(L, 2)); + lua_pushinteger(L, c); + return 1; +} + int L_SetColor(lua_State* L) { Set_color(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tonumber(L, 3), @@ -60,29 +105,11 @@ int L_SetColor(lua_State* L) void Button_Brush_Factory(void) { short clicked_button; - word height; - word width; - char str[5]; - - T_Special_button* width_button; - T_Special_button* height_button; Open_window(154, 162, "Brush Factory"); Window_set_normal_button(77, 141, 67, 14, "Cancel", 0, 1, KEY_ESC); // 1 Window_set_normal_button(10, 141, 67, 14, "Run", 0, 1, 0); // 2 - Print_in_window(10, 17, "Width:", MC_Black, MC_Light); - width_button = Window_set_input_button(64, 15, 4); // 3 - Print_in_window(10, 30, "Height:", MC_Black, MC_Light); - height_button = Window_set_input_button(64, 28, 4); // 4 - - width = Paintbrush_width; - Num2str(width, str, 4); - Window_input_content(width_button, str); - - height = Paintbrush_height; - Num2str(height, str, 4); - Window_input_content(height_button, str); Update_window_area(0, 0, Window_width, Window_height); Display_cursor(); @@ -92,34 +119,6 @@ void Button_Brush_Factory(void) switch (clicked_button) { - case 3 : // Largeur - Num2str(width, str, 4); - Readline(65, 16, str, 4, 1); - width = atoi(str); - // On corrige les dimensions - if (width == 0) - { - width = 1; - Num2str(width, str, 4); - Window_input_content(width_button, str); - } - Display_cursor(); - break; - - case 4 : // Height - Num2str(height, str, 4); - Readline(65, 29, str, 4, 1); - height = atoi(str); - // On corrige les dimensions - if (height == 0) - { - height = 1; - Num2str(height, str, 4); - Window_input_content(height_button, str); - } - Display_cursor(); - break; - default: break; } @@ -130,23 +129,25 @@ void Button_Brush_Factory(void) { lua_State* L = lua_open(); - Realloc_brush(width, height); - - lua_register(L,"putpixel",L_PutPixel); - lua_register(L,"getpixel",L_GetPixel); + lua_register(L,"putbrushpixel",L_PutBrushPixel); + lua_register(L,"getbrushpixel",L_GetBrushPixel); + lua_register(L,"putpicturepixel",L_PutPicturePixel); + lua_register(L,"getpicturepixel",L_GetPicturePixel); + lua_register(L,"setbrushsize",L_SetBrushSize); + lua_register(L,"setpicturesize",L_SetPictureSize); + lua_register(L,"getbrushsize",L_GetBrushSize); + lua_register(L,"getpicturesize",L_GetPictureSize); lua_register(L,"setcolor",L_SetColor); + // For debug only + // luaL_openlibs(L); + if (luaL_loadfile(L,"./test.lua") != 0) Verbose_error_message(lua_tostring(L, 1)); - - lua_pushinteger(L, width); - lua_pushinteger(L, height); - if (lua_pcall(L, 2, 0, 0) != 0) + else if (lua_pcall(L, 0, 0, 0) != 0) Verbose_error_message(lua_tostring(L, 1)); lua_close(L); - - Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH); } Close_window(); diff --git a/test.lua b/test.lua new file mode 100644 index 00000000..a8804d1d --- /dev/null +++ b/test.lua @@ -0,0 +1,7 @@ +w, h = getbrushsize() + +for x = 0, w - 1, 1 do + for y = 0, h - 1, 1 do + putbrushpixel(x, y, (x+y)%256); + end +end From b0aa1dcbab898111b1f0ac73d5e2cf3fffcb0102 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 29 Oct 2009 22:05:14 +0000 Subject: [PATCH 09/30] Added Ok and Cancel buttons in value requester. Don't do anything in palette screen if user enters strange value, not even a reduction to 256 as this drops unused colors. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1100 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- palette.c | 49 ++++++++++++++++++++++++++----------------------- windows.c | 8 +++++--- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/palette.c b/palette.c index 38a33637..b308b918 100644 --- a/palette.c +++ b/palette.c @@ -1466,36 +1466,39 @@ void Button_Palette(void) reduce_colors_number = Requester_window("Enter the max. number of colors", reduce_colors_number); - if (reduce_colors_number < 2 || reduce_colors_number > 256) - reduce_colors_number = 256; + if (reduce_colors_number < 2 || reduce_colors_number >= 256) + reduce_colors_number = -1; break; } - if (!image_is_backed_up) - { - Backup(); - image_is_backed_up = 1; - } + if (reduce_colors_number > 0) + { + if (!image_is_backed_up) + { + Backup(); + image_is_backed_up = 1; + } - Reduce_palette(&used_colors, reduce_colors_number, working_palette, - color_usage); + Reduce_palette(&used_colors, reduce_colors_number, working_palette, + color_usage); - if ((Config.Safety_colors) && (used_colors<4)) - { - memcpy(temp_palette, Main_palette, sizeof(T_Palette)); - memcpy(Main_palette, working_palette, sizeof(T_Palette)); - Set_nice_menu_colors(color_usage, 0); - memcpy(working_palette, Main_palette, sizeof(T_Palette)); - memcpy(Main_palette, temp_palette, sizeof(T_Palette)); - } + if ((Config.Safety_colors) && (used_colors<4)) + { + memcpy(temp_palette, Main_palette, sizeof(T_Palette)); + memcpy(Main_palette, working_palette, sizeof(T_Palette)); + Set_nice_menu_colors(color_usage, 0); + memcpy(working_palette, Main_palette, sizeof(T_Palette)); + memcpy(Main_palette, temp_palette, sizeof(T_Palette)); + } - Set_palette(working_palette); // On définit la nouvelle palette - Draw_all_palette_sliders(red_slider, green_slider, blue_slider, - working_palette, block_start, block_end); - memcpy(temp_palette, working_palette, sizeof(T_Palette)); + Set_palette(working_palette); // On définit la nouvelle palette + Draw_all_palette_sliders(red_slider, green_slider, blue_slider, + working_palette, block_start, block_end); + memcpy(temp_palette, working_palette, sizeof(T_Palette)); - End_of_modification(); - need_to_remap = 1; + End_of_modification(); + need_to_remap = 1; + } break; case 12: // Undo diff --git a/windows.c b/windows.c index e6da7849..8f0f311d 100644 --- a/windows.c +++ b/windows.c @@ -856,8 +856,10 @@ int Requester_window(char* message, int initial_value) Print_in_window((window_width>>1)-(strlen(message)<<2), 20, message, MC_Black, MC_Light); sprintf(str, "%d", initial_value); - Window_set_input_button((window_width / 3) - 20, 37, 10); // 1 - Print_in_window((window_width / 3) - 18, 39, str, MC_Black, MC_Light); + Window_set_input_button(10, 37, 4); // 1 + Print_in_window(11, 39, str, MC_Black, MC_Light); + Window_set_normal_button(60 ,37,40,14,"OK",1,1,SDLK_y); // 2 + Window_set_normal_button(130,37,60,14,"Cancel" ,1,1,SDLK_n); // 3 Update_rect(Window_pos_X, Window_pos_Y, Menu_factor_X * window_width, Menu_factor_Y * 60); @@ -867,7 +869,7 @@ int Requester_window(char* message, int initial_value) { clicked_button = Window_clicked_button(); if (clicked_button == 1) - Readline((window_width / 3) - 18, 39, str, 10, 1); + Readline(11, 39, str, 4, 1); if (Key == SDLK_ESCAPE) clicked_button = 2; } while (clicked_button <= 0); From 0694f69c9c2d379c08e7e8f3cde8b6cf6f003857 Mon Sep 17 00:00:00 2001 From: Yves Rizoud Date: Thu, 29 Oct 2009 22:50:34 +0000 Subject: [PATCH 10/30] trunk: Lua binding works on Windows. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1101 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- Makefile | 7 ++++--- doc/COMPILING.txt | 19 ++++++++++++++++--- doc/README-lua.txt | 24 ++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 doc/README-lua.txt diff --git a/Makefile b/Makefile index 3397ccf4..19c9be21 100644 --- a/Makefile +++ b/Makefile @@ -42,15 +42,16 @@ ifdef COMSPEC RMDIR = rmdir CP = cp BIN = grafx2.exe - COPT = -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -g -ggdb `sdl-config --cflags` $(TTFCOPT) $(JOYCOPT) - LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng + COPT = -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -g -ggdb `sdl-config --cflags` $(TTFCOPT) $(JOYCOPT) $(LUACOPT) + LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng $(LUALOPT) CC = gcc OBJDIR = obj/win32 # Resources (icon) WINDRES = windres.exe PLATFORMOBJ = $(OBJDIR)/winres.o PLATFORM = win32 - PLATFORMFILES = SDL.dll SDL_image.dll libpng13.dll zlib1.dll gfx2.ico $(TTFLIBS) #some misc files we have to add to the release archive under windows. + #some misc files we have to add to the release archive under windows. + PLATFORMFILES = SDL.dll SDL_image.dll libpng13.dll zlib1.dll gfx2.ico $(TTFLIBS) ZIP = zip else diff --git a/doc/COMPILING.txt b/doc/COMPILING.txt index a6ea24be..65ff40cc 100644 --- a/doc/COMPILING.txt +++ b/doc/COMPILING.txt @@ -68,6 +68,11 @@ To compile a gp2x executable, type This will only work on an UNIXsystem (Linux or FreeBSD). == Windows == + +It is also possible to compile from linux, with this command : + make WIN32CROSS=1 +You will need the mingw cross-compiler, and all the librairies listed above. + Here are the resources used to build the Windows version: 4DOS @@ -141,6 +146,14 @@ SDL_ttf: SDL_ttf-2.0.9-win32.zip for DLLs: libfreetype-6.dll, SDL_ttf.dll, zlib1.dll SDL_ttf-2.0.9.tar.gz -It is also possible to compile from linux, with this command : - make WIN32CROSS=1 -You will need the mingw cross-compiler, and all the librairies listed above. +Lua: + (optional) + http://www.lua.org/ftp/lua-5.1.4.tar.gz + Uncompress in temporary directory + Use sh shell + make mingw + (make install doesn't work, even with prefix) + Copy luaconf.h, lualib.h, lua.h, lauxlib.h to c:\msys\mingw\include\lua5.1 + Copy liblua.a to c:\msys\mingw\lib RENAMED AS liblua5.1.a + Copy lua51.dll to c:\msys\mingw\bin + diff --git a/doc/README-lua.txt b/doc/README-lua.txt new file mode 100644 index 00000000..2d8a0b44 --- /dev/null +++ b/doc/README-lua.txt @@ -0,0 +1,24 @@ +The Windows distribution of Grafx2 is compiled and statically linked with +Lua v5.1.4 + +Lua is licensed with the MIT license: + +Copyright © 1994-2008 Lua.org, PUC-Rio. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 0ae98c2e56fa700aa9fb1d8861cead8304345dc9 Mon Sep 17 00:00:00 2001 From: Yves Rizoud Date: Thu, 29 Oct 2009 23:35:59 +0000 Subject: [PATCH 11/30] Makefile fixes for lua packaging git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1102 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 19c9be21..f3e7bc5d 100644 --- a/Makefile +++ b/Makefile @@ -315,9 +315,9 @@ ziprelease: version $(BIN) release echo `sed "s/.*=\"\(.*\)\";/\1/" pversion.c`.`svnversion` | tr " :" "_-" | sed -e s/\\(wip\\)\\\\./\\1/I > $(OBJDIR)/versiontag tar cvzf "src-`cat $(OBJDIR)/versiontag`.tgz" --transform 's,^,src/,g' *.c *.h Makefile Makefile.dep gfx2.ico - $(ZIP) $(ZIPOPT) "grafx2-`cat $(OBJDIR)/versiontag`$(TTFLABEL)-$(PLATFORM).$(ZIP)" $(BIN) gfx2def.ini $(SKIN_FILES) gfx2.gif doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt fonts/8pxfont.png doc/README-zlib1.txt doc/README-SDL.txt doc/README-SDL_image.txt doc/README-SDL_ttf.txt fonts/Tuffy.ttf src-`cat $(OBJDIR)/versiontag`.tgz $(PLATFORMFILES) + $(ZIP) $(ZIPOPT) "grafx2-`cat $(OBJDIR)/versiontag`$(TTFLABEL)-$(PLATFORM).$(ZIP)" $(BIN) gfx2def.ini test.lua $(SKIN_FILES) gfx2.gif doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt fonts/8pxfont.png doc/README-zlib1.txt doc/README-SDL.txt doc/README-SDL_image.txt doc/README-SDL_ttf.txt doc/README-lua.txt fonts/Tuffy.ttf src-`cat $(OBJDIR)/versiontag`.tgz $(PLATFORMFILES) $(DELCOMMAND) "src-`cat $(OBJDIR)/versiontag`.tgz" - tar cvzf "grafx2-`cat $(OBJDIR)/versiontag`$(TTFLABEL)-src.tgz" --transform 's,^,grafx2/,g' *.c *.h Makefile Makefile.dep gfx2def.ini $(SKIN_FILES) gfx2.ico gfx2.gif doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt misc/grafx2.1 misc/grafx2.xpm misc/grafx2.desktop fonts/8pxfont.png fonts/Tuffy.ttf + tar cvzf "grafx2-`cat $(OBJDIR)/versiontag`$(TTFLABEL)-src.tgz" --transform 's,^,grafx2/,g' *.c *.h Makefile Makefile.dep gfx2def.ini test.lua $(SKIN_FILES) gfx2.ico gfx2.gif doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt misc/grafx2.1 misc/grafx2.xpm misc/grafx2.desktop fonts/8pxfont.png fonts/Tuffy.ttf $(DELCOMMAND) "$(OBJDIR)/versiontag" testsed : From 9b451345968ae4d3687f6432e7429173be92bbf7 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Fri, 30 Oct 2009 10:26:44 +0000 Subject: [PATCH 12/30] Apply patch from issue 223 and some more tweaks as later suggested in the comments. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1103 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- shade.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/shade.c b/shade.c index 32d0dfed..31a41cf4 100644 --- a/shade.c +++ b/shade.c @@ -22,6 +22,7 @@ #include "global.h" #include "graph.h" #include "engine.h" +#include "errors.h" #include "misc.h" #include "readline.h" #include "help.h" @@ -432,18 +433,18 @@ void Swap_shade(short block_1_start,short block_2_start,short block_size) int Menu_shade(void) { - short clicked_button; // Numéro du bouton sur lequel l'utilisateur a clické - char str[4]; // str d'affichage du n° de shade actif et du Pas - word old_mouse_x,old_mouse_x2; // Mémo. de l'ancienne pos. du curseur - word old_mouse_y,old_mouse_y2; - byte old_mouse_k,old_mouse_k2; + short clicked_button; // Numéro du bouton sur lequel l'utilisateur a clické + char str[4]; // str d'affichage du n° de shade actif et du Pas + word old_mouse_x, old_mouse_x2; // Mémo. de l'ancienne pos. du curseur + word old_mouse_y, old_mouse_y2; + byte old_mouse_k, old_mouse_k2; byte temp_color; // Variables de gestion des clicks dans la palette - byte first_color=0; - byte last_color=0; - word selection_start=0; - word selection_end=0; + byte first_color = Fore_color; + byte last_color = Fore_color; + word selection_start = 0; + word selection_end = 0; T_Special_button * input_button; - short temp,temp2; + short temp, temp2; word temp_cell; word * buffer; // buffer du Copy/Paste word * undo_buffer; // buffer du Undo @@ -477,7 +478,7 @@ int Menu_shade(void) Window_set_normal_button(234,87,43,14,"Paste" ,1,1,SDLK_p); // 7 // On tagge le bloc - Tag_color_range(0,0); + Tag_color_range(Fore_color,Fore_color); // Tracé d'un cadre creux autour du bloc dégradé Window_display_frame_in(171,26,18,66); @@ -614,6 +615,13 @@ int Menu_shade(void) } break; + case 5: // Ok + if (selection_start == selection_end && Shade_list[Shade_current].List[selection_start] > 0) + Set_fore_color(Shade_list[Shade_current].List[selection_start]); + else if (first_color == last_color) + Set_fore_color(first_color); + break; + case 6 : // Copy memcpy(buffer,Shade_list[Shade_current].List,512*sizeof(word)); break; From 56a4c704feb0fdee797cc820f72d99db1396622a Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Fri, 30 Oct 2009 10:45:52 +0000 Subject: [PATCH 13/30] Added lua binding to select the color brush. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1104 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- factory.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/factory.c b/factory.c index 89991563..6c6e068c 100644 --- a/factory.c +++ b/factory.c @@ -102,6 +102,12 @@ int L_SetColor(lua_State* L) return 0; } +int L_BrushEnable(lua_State* L) +{ + Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH); + return 0; +} + void Button_Brush_Factory(void) { short clicked_button; @@ -138,6 +144,7 @@ void Button_Brush_Factory(void) lua_register(L,"getbrushsize",L_GetBrushSize); lua_register(L,"getpicturesize",L_GetPictureSize); lua_register(L,"setcolor",L_SetColor); + lua_register(L,"brushenable",L_BrushEnable); // For debug only // luaL_openlibs(L); @@ -151,6 +158,7 @@ void Button_Brush_Factory(void) } Close_window(); + Unselect_button(BUTTON_BRUSH_EFFECTS); Display_cursor(); } From 7af6b92e3e384760d6ead61ea7cb2e19c821adef Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Fri, 30 Oct 2009 11:51:07 +0000 Subject: [PATCH 14/30] Reset quicksearch when entering a directory. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1106 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- filesel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/filesel.c b/filesel.c index 74dd7d33..5759c34d 100644 --- a/filesel.c +++ b/filesel.c @@ -1644,6 +1644,9 @@ byte Button_Load_or_Save(byte load, byte image) Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller); Display_cursor(); New_preview_is_needed=1; + + // On est dans un nouveau répertoire, donc on remet le quicksearch à 0 + *quicksearch_filename=0; } else // Sinon on essaye de charger ou sauver le fichier { From f4defe7e75850e2bd645d26253ac4b16e69ee356 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Fri, 30 Oct 2009 15:19:59 +0000 Subject: [PATCH 15/30] Moved "show limits" and "separate colors" to skin dialog git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1107 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- buttons.c | 312 ++++++++++++++++-------------------------------------- 1 file changed, 92 insertions(+), 220 deletions(-) diff --git a/buttons.c b/buttons.c index 420a4579..4a420469 100644 --- a/buttons.c +++ b/buttons.c @@ -713,43 +713,15 @@ void Settings_display_config(T_Config * conf) Print_in_window(273, 31,(conf->Show_hidden_files)?YES:NO,MC_Black,MC_Light); Print_in_window(273, 46,(conf->Show_hidden_directories)?YES:NO,MC_Black,MC_Light); -// Print_in_window(273, 61,(conf->Show_system_directories)?YES:NO,MC_Black,MC_Light); Print_in_window(223, 84,(conf->Safety_colors)?YES:NO,MC_Black,MC_Light); Print_in_window(223, 99,(conf->Adjust_brush_pick)?YES:NO,MC_Black,MC_Light); - Print_in_window(223,114,(conf->Separate_colors)?YES:NO,MC_Black,MC_Light); - Print_in_window(223,129,(conf->Auto_set_res)?YES:NO,MC_Black,MC_Light); - Print_in_window(183,144,(conf->Coords_rel)?"Relative":"Absolute",MC_Black,MC_Light); + Print_in_window(223,114,(conf->Auto_set_res)?YES:NO,MC_Black,MC_Light); + Print_in_window(183,129,(conf->Coords_rel)?"Relative":"Absolute",MC_Black,MC_Light); - Print_in_window( 91, 84,(conf->Display_image_limits)?YES:NO,MC_Black,MC_Light); - Print_in_window( 91, 99,(conf->Clear_palette)?YES:NO,MC_Black,MC_Light); - Print_in_window( 91,114,(conf->Maximize_preview)?YES:NO,MC_Black,MC_Light); - Print_in_window( 91,129,(conf->Backup)?YES:NO,MC_Black,MC_Light); - /* - switch (conf->Cursor) - { - case 0 : Print_in_window(67,144," Solid",MC_Black,MC_Light); break; - case 1 : Print_in_window(67,144,"Transp",MC_Black,MC_Light); break; - default: Print_in_window(67,144," Thin",MC_Black,MC_Light); - } - */ - - /* - if (conf->Font) - { // Fun - Print_in_window( 8,31," ",MC_Black,MC_Light); - Print_in_window( 78,31," ",MC_Black,MC_Light); - Print_in_window( 82,31,"\020",MC_Black,MC_Light); - Print_in_window(152,31,"\021",MC_Black,MC_Light); - } - else - { // Classic - Print_in_window( 82,31," ",MC_Black,MC_Light); - Print_in_window(152,31," ",MC_Black,MC_Light); - Print_in_window( 8,31,"\020",MC_Black,MC_Light); - Print_in_window( 78,31,"\021",MC_Black,MC_Light); - } - */ + Print_in_window( 91, 84,(conf->Clear_palette)?YES:NO,MC_Black,MC_Light); + Print_in_window( 91, 99,(conf->Maximize_preview)?YES:NO,MC_Black,MC_Light); + Print_in_window( 91,114,(conf->Backup)?YES:NO,MC_Black,MC_Light); Print_in_window(155,166,(conf->Auto_save)?YES:NO,MC_Black,MC_Light); @@ -807,41 +779,35 @@ void Button_Settings(void) Window_set_normal_button(167, 28,131,14,"Hidden files: ",0,1,SDLK_LAST); // 1 Window_set_normal_button(167, 43,131,14,"Hidden dir. : ",0,1,SDLK_LAST); // 2 - // Button Show/Hide Picture limits - Window_set_normal_button( 9, 81,107,14,"Limits : ",0,1,SDLK_LAST); // 3 - // Button Show/Hide Picture limits - Window_set_normal_button( 9, 96,107,14,"Clear pal: ",0,1,SDLK_LAST); // 4 - // Button Show/Hide Picture limits - Window_set_normal_button( 9,111,107,14,"Max prev.: ",0,1,SDLK_LAST); // 5 + Window_set_normal_button(9, 81, 107, 14, "Clear pal: ", 0, 1, SDLK_LAST); // 3 + Window_set_normal_button(9, 96, 107, 14, "Max prev.: ", 0, 1, SDLK_LAST); // 4 // Button Effectuer des backups à chaque sauvegarde - Window_set_normal_button( 9,126,107,14,"Backup : ",0,1,SDLK_LAST); // 6 + Window_set_normal_button( 9,111,107,14,"Backup : ",0,1,SDLK_LAST); // 5 // Button Safety colors - Window_set_normal_button(117, 81,131,14,"Safe. colors: ",0,1,SDLK_LAST); // 7 + Window_set_normal_button(117, 81,131,14,"Safe. colors: ",0,1,SDLK_LAST); // 6 // Button Adjust Brush Pick - Window_set_normal_button(117, 96,131,14,"AdjBrushPick: ",0,1,SDLK_LAST); // 8 - // Button Separate colors - Window_set_normal_button(117,111,131,14,"Separate col: ",0,1,SDLK_LAST); // 9 + Window_set_normal_button(117, 96,131,14,"AdjBrushPick: ",0,1,SDLK_LAST); // 7 // Button Passer dans la résolution appropriée après un chargement - Window_set_normal_button(117,126,131,14,"Auto-set res: ",0,1,SDLK_LAST); // 10 + Window_set_normal_button(117,111,131,14,"Auto-set res: ",0,1,SDLK_LAST); // 8 // Button Adapter la palette après un chargement (<=> Shift+BkSpc) - Window_set_normal_button(117,141,131,14,"Coords: ",0,1,SDLK_LAST); // 11 + Window_set_normal_button(117,126,131,14,"Coords: ",0,1,SDLK_LAST); // 9 // Button Reload - Window_set_normal_button( 6,163, 51,14,"Reload" ,0,1,SDLK_LAST); // 12 + Window_set_normal_button( 6,163, 51,14,"Reload" ,0,1,SDLK_LAST); // 10 // Button Auto-save - Window_set_normal_button( 73,163,107,14,"Auto-save: ",0,1,SDLK_LAST); // 13 + Window_set_normal_button( 73,163,107,14,"Auto-save: ",0,1,SDLK_LAST); // 11 // Button Save - Window_set_normal_button(183,163, 51,14,"Save" ,0,1,SDLK_LAST); // 14 + Window_set_normal_button(183,163, 51,14,"Save" ,0,1,SDLK_LAST); // 12 // Button Close - Window_set_normal_button(250,163, 51,14,"Close" ,0,1,KEY_ESC); // 15 + Window_set_normal_button(250,163, 51,14,"Close" ,0,1,KEY_ESC); // 13 // Jauges de sensibilité de la souris (X puis Y) - Window_set_scroller_button(265,99,56,4,1,0); // 16 - Window_set_scroller_button(279,99,56,4,1,0); // 17 + Window_set_scroller_button(265,99,56,4,1,0); // 14 + Window_set_scroller_button(279,99,56,4,1,0); // 15 // Zone de saisie du nb de pages de Undo - Window_set_input_button(140,50,2); // 18 + Window_set_input_button(140,50,2); // 16 Update_window_area(0,0,Window_width, Window_height); @@ -862,54 +828,45 @@ void Button_Settings(void) case 2 : // Hidden dir. Config_choisie.Show_hidden_directories=(Config_choisie.Show_hidden_directories)?0:-1; break; -// case 5 : // System dir. -// Config_choisie.Show_system_directories=(Config_choisie.Show_system_directories)?0:-1; -// break; - case 3 : // Draw limits - Config_choisie.Display_image_limits=!Config_choisie.Display_image_limits; - break; - case 4 : // Clear palette + case 3 : // Clear palette Config_choisie.Clear_palette=!Config_choisie.Clear_palette; break; - case 5 : // Maximize preview + case 4 : // Maximize preview Config_choisie.Maximize_preview=!Config_choisie.Maximize_preview; break; - case 6 : // Backup + case 5 : // Backup Config_choisie.Backup=!Config_choisie.Backup; break; - case 7 : // Safety colors + case 6 : // Safety colors Config_choisie.Safety_colors=!Config_choisie.Safety_colors; break; - case 8 : // Adjust brush pick + case 7 : // Adjust brush pick Config_choisie.Adjust_brush_pick=!Config_choisie.Adjust_brush_pick; break; - case 9 : // Separate colors - Config_choisie.Separate_colors=!Config_choisie.Separate_colors; - break; - case 10 : // Auto-set resolution + case 8 : // Auto-set resolution Config_choisie.Auto_set_res=!Config_choisie.Auto_set_res; break; - case 11 : // Coordonnées + case 9 : // Coordonnées Config_choisie.Coords_rel=!Config_choisie.Coords_rel; break; - case 12 : // Reload + case 10 : // Reload Settings_load_config(&Config_choisie); config_is_reloaded=1; break; - case 13 : // Auto-save + case 11 : // Auto-save Config_choisie.Auto_save=!Config_choisie.Auto_save; break; - case 14 : // Save + case 12 : // Save Settings_save_config(&Config_choisie); break; - // 15 : OK - case 16 : // X Sensib. + // 13 close + case 14 : // X Sensib. Config_choisie.Mouse_sensitivity_index_x=Window_attribute2+1; break; - case 17 : // Y Sensib. + case 15 : // Y Sensib. Config_choisie.Mouse_sensitivity_index_y=Window_attribute2+1; break; - case 18 : // Nb pages Undo + case 16 : // Nb pages Undo Num2str(Config_choisie.Max_undo_pages,str,2); Readline(142,52,str,2,1); Config_choisie.Max_undo_pages=atoi(str); @@ -939,15 +896,15 @@ void Button_Settings(void) Spare_fileselector_offset=0; } - if ((clicked_button>=1) && (clicked_button<15)) + if ((clicked_button>=1) && (clicked_button<13)) Settings_display_config(&Config_choisie); if (Is_shortcut(Key,0x100+BUTTON_HELP)) Window_help(BUTTON_SETTINGS, NULL); else if (Is_shortcut(Key,0x100+BUTTON_SETTINGS)) - clicked_button=15; + clicked_button=13; } - while ( (clicked_button!=15) && (Key!=SDLK_RETURN) ); + while ( (clicked_button!=13) && (Key!=SDLK_RETURN) ); Config=Config_choisie; @@ -956,7 +913,7 @@ void Button_Settings(void) Close_window(); Unselect_button(BUTTON_SETTINGS); - // Raffichage du menu pour que les inscriptions qui y figurent soient + // Raffichage du menu pour que les inscriptions qui y figurent soient // retracées avec la nouvelle fonte Display_menu(); Display_cursor(); @@ -1059,8 +1016,10 @@ void Button_Skins(void) T_Dropdown_button * cursor_dropdown; T_List_button * skin_list; T_Scroller_button * file_scroller; - int selected_font=0; - int selected_cursor=Config.Cursor; + int selected_font = 0; + int selected_cursor = Config.Cursor; + byte separatecolors = Config.Separate_colors; + byte showlimits = Config.Display_image_limits; char * cursors[] = { "Solid", "Transparent", "Thin" }; @@ -1073,8 +1032,8 @@ void Button_Skins(void) Free_fileselector_list(&Skin_files_list); Free_fileselector_list(&Font_files_list); // Browse the "skins" directory - strcpy(skinsdir,Data_directory); - strcat(skinsdir,"skins"); + strcpy(skinsdir, Data_directory); + strcat(skinsdir, "skins"); // Add each found file to the list For_each_file(skinsdir, Add_font_or_skin); // Sort it @@ -1085,25 +1044,25 @@ void Button_Skins(void) // -------------------------------------------------------------- - Open_window(178,155,"Skins"); + Open_window(290, 140, "Skins"); // Frames - Window_display_frame_in(6,FILESEL_Y-2,148,84); // File selector + Window_display_frame_in(6, FILESEL_Y - 2, 148, 84); // File selector // Texts Print_in_window( 6, 21,"Font" ,MC_Black,MC_Light); Print_in_window( 6, 36,"Cursor" ,MC_Black,MC_Light); // Ok button - Window_set_normal_button(6,136, 51,14,"OK" ,0,1,SDLK_RETURN); // 1 + Window_set_normal_button(172, 120, 51, 14, "OK", 0, 1, SDLK_RETURN); // 1 // List of skins skin_list = Window_set_list_button( // Fileselector - Window_set_special_button(8,FILESEL_Y+1,144,80), // 2 + Window_set_special_button(8, FILESEL_Y + 1, 144, 80), // 2 // Scroller for the fileselector - (file_scroller = Window_set_scroller_button(160,FILESEL_Y+1,82, - Skin_files_list.Nb_elements,10,0)), // 3 + (file_scroller = Window_set_scroller_button(155, FILESEL_Y - 1, 82, + Skin_files_list.Nb_elements, 10, 0)), // 3 Draw_one_skin_name); // 4 skin_list->Cursor_position = Find_file_in_fileselector(&Skin_files_list, Config.Skin_file); @@ -1114,12 +1073,23 @@ void Button_Skins(void) Window_dropdown_add_item(font_dropdown,temp,Get_item_by_index(&Font_files_list,temp)->Short_name); // Cancel - Window_set_normal_button(62,136, 51,14,"Cancel",0,1,SDLK_ESCAPE); // 6 + Window_set_normal_button(227, 120, 51,14,"Cancel",0,1,SDLK_ESCAPE); // 6 // Dropdown list to choose cursor type - cursor_dropdown = Window_set_dropdown_button(60,34,104,11,0,cursors[selected_cursor],1,0,1,RIGHT_SIDE|LEFT_SIDE); // 7 - for (temp=0; temp<3; temp++) - Window_dropdown_add_item(cursor_dropdown,temp,cursors[temp]); + cursor_dropdown = Window_set_dropdown_button(60, 34, 104, 11, 0, + cursors[selected_cursor], 1, 0, 1, RIGHT_SIDE|LEFT_SIDE); // 7 + for (temp = 0; temp<3; temp++) + Window_dropdown_add_item(cursor_dropdown, temp, cursors[temp]); + + Window_set_normal_button(172, 23, 14, 14, + (Config.Display_image_limits)?"X":" ", -1, 1, SDLK_LAST); // 8 + Print_in_window( 190, 21,"Draw picture", MC_Dark, MC_Light); + Print_in_window( 190, 30,"limits", MC_Dark, MC_Light); + + Window_set_normal_button(172, 52, 14, 14, + (Config.Separate_colors)?"X":" ", -1, 1, SDLK_LAST); // 9 + Print_in_window( 190, 50,"Separate", MC_Dark, MC_Light); + Print_in_window( 190, 59,"colors", MC_Dark, MC_Light); Window_redraw_list(skin_list); @@ -1133,133 +1103,33 @@ void Button_Skins(void) switch(clicked_button) { - case 1 : // OK - break; - case 2 : // doesn't happen + case 1 : // OK + break; + case 2 : // doesn't happen + break; + case 3 : // doesn't happen + break; + case 4 : // a file is selected + break; + case 5 : // Font dropdown + selected_font = Window_attribute2; // Get the index of the chosen font. + break; + // 6: Cancel + case 7 : // Cursor + selected_cursor = Window_attribute2; break; - case 3 : // doesn't happen - break; - case 4 : // a file is selected - break; - case 5 : // Font dropdown - selected_font=Window_attribute2; // Get the index of the chosen font. - break; - // 5: Cancel - case 7 : // Cursor - selected_cursor = Window_attribute2; - break; - } - - switch (Key) - { - case SDLK_UNKNOWN : break; - /* - case SDLK_DOWN : // Bas - *quicksearch_filename=0; - Hide_cursor(); - Selector_scroll_down(&Main_fileselector_position,&Main_fileselector_offset); - if (file_scroller->Position!=Main_fileselector_position) - { - // Si c'est le cas, il faut mettre à jour la jauge - file_scroller->Position=Main_fileselector_position; - Window_draw_slider(file_scroller); - } - Key=0; - break; - case SDLK_UP : // Haut - *quicksearch_filename=0; - Hide_cursor(); - Selector_scroll_up(&Main_fileselector_position,&Main_fileselector_offset); - if (file_scroller->Position!=Main_fileselector_position) - { - // Si c'est le cas, il faut mettre à jour la jauge - file_scroller->Position=Main_fileselector_position; - Window_draw_slider(file_scroller); - } - Key=0; - break; - case SDLK_PAGEDOWN : // PageDown - case KEY_MOUSEWHEELDOWN : - *quicksearch_filename=0; - Hide_cursor(); - Selector_page_down(&Main_fileselector_position,&Main_fileselector_offset,9); - if (file_scroller->Position!=Main_fileselector_position) - { - // Si c'est le cas, il faut mettre à jour la jauge - file_scroller->Position=Main_fileselector_position; - Window_draw_slider(file_scroller); - } - Key=0; - break; - case SDLK_PAGEUP : // PageUp - case KEY_MOUSEWHEELUP : - *quicksearch_filename=0; - Hide_cursor(); - Selector_page_up(&Main_fileselector_position,&Main_fileselector_offset,9); - if (file_scroller->Position!=Main_fileselector_position) - { - // Si c'est le cas, il faut mettre à jour la jauge - file_scroller->Position=Main_fileselector_position; - Window_draw_slider(file_scroller); - } - Key=0; - break; - case SDLK_END : // End - *quicksearch_filename=0; - Hide_cursor(); - Selector_end(&Main_fileselector_position,&Main_fileselector_offset); - if (file_scroller->Position!=Main_fileselector_position) - { - // Si c'est le cas, il faut mettre à jour la jauge - file_scroller->Position=Main_fileselector_position; - Window_draw_slider(file_scroller); - } - Key=0; - break; - case SDLK_HOME : // Home - *quicksearch_filename=0; - Hide_cursor(); - Selector_home(&Main_fileselector_position,&Main_fileselector_offset); - if (file_scroller->Position!=Main_fileselector_position) - { - // Si c'est le cas, il faut mettre à jour la jauge - file_scroller->Position=Main_fileselector_position; - Window_draw_slider(file_scroller); - } - Key=0; - break; - default: // Autre => On se place sur le nom de fichier qui correspond - if (clicked_button<=0) - { - if (Is_shortcut(Key,0x100+BUTTON_HELP)) - { - Window_help(BUTTON_SETTINGS, NULL); - break; - } - temp=strlen(quicksearch_filename); - if (Key_ANSI>= ' ' && Key_ANSI < 255 && temp<50) - { - quicksearch_filename[temp]=Key_ANSI; - quicksearch_filename[temp+1]='\0'; - most_matching_filename=Find_filename_match(Skin_files_list, quicksearch_filename); - if ( (most_matching_filename) ) - { - temp=Main_fileselector_position+Main_fileselector_offset; - Hide_cursor(); - Highlight_file(most_matching_filename); - Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller); - Display_cursor(); - if (temp!=Main_fileselector_position+Main_fileselector_offset) - New_preview_is_needed=1; - } - else - *quicksearch_filename=0; - Key=0; - } - } - else - *quicksearch_filename=0; - */ + case 8: // Display limits + showlimits = !showlimits; + Hide_cursor(); + Print_in_window(175, 26, (showlimits)?"X":" ", MC_Black, MC_Light); + Display_cursor(); + break; + case 9: // Separate colors + separatecolors = !separatecolors; + Hide_cursor(); + Print_in_window(175, 55, (separatecolors)?"X":" ", MC_Black, MC_Light); + Display_cursor(); + break; } } while ( (clicked_button!=1) && (clicked_button !=6) && (Key != SDLK_ESCAPE)); @@ -1298,6 +1168,8 @@ void Button_Skins(void) } // Confirm the change of cursor shape Config.Cursor = selected_cursor; + Config.Display_image_limits = showlimits; + Config.Separate_colors = separatecolors; } Close_window(); From 0661e59e1c84e29589c5fa729a9a2e7c570ac01c Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Fri, 30 Oct 2009 16:58:37 +0000 Subject: [PATCH 16/30] Preview skins. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1108 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- buttons.c | 69 +++++++++++++++++++++++++---------------- global.h | 3 ++ init.c | 6 ++++ skins/skin_classic.png | Bin 14352 -> 14069 bytes skins/skin_modern.png | Bin 16553 -> 16271 bytes 5 files changed, 51 insertions(+), 27 deletions(-) diff --git a/buttons.c b/buttons.c index 4a420469..5732e5b8 100644 --- a/buttons.c +++ b/buttons.c @@ -1020,10 +1020,13 @@ void Button_Skins(void) int selected_cursor = Config.Cursor; byte separatecolors = Config.Separate_colors; byte showlimits = Config.Display_image_limits; + + word x,y, x_pos, offs_y; char * cursors[] = { "Solid", "Transparent", "Thin" }; + T_Gui_skin * gfx = NULL; - #define FILESEL_Y 52 + #define FILESEL_Y 34 // --- Read the contents of skins/ directory ------------------ @@ -1050,11 +1053,11 @@ void Button_Skins(void) Window_display_frame_in(6, FILESEL_Y - 2, 148, 84); // File selector // Texts - Print_in_window( 6, 21,"Font" ,MC_Black,MC_Light); - Print_in_window( 6, 36,"Cursor" ,MC_Black,MC_Light); + Print_in_window( 172, 33,"Font:" ,MC_Black,MC_Light); + Print_in_window( 172, 59,"Cursor:" ,MC_Black,MC_Light); // Ok button - Window_set_normal_button(172, 120, 51, 14, "OK", 0, 1, SDLK_RETURN); // 1 + Window_set_normal_button(6, 120, 51, 14, "OK", 0, 1, SDLK_RETURN); // 1 // List of skins skin_list = Window_set_list_button( @@ -1068,31 +1071,35 @@ void Button_Skins(void) skin_list->Cursor_position = Find_file_in_fileselector(&Skin_files_list, Config.Skin_file); // Buttons to choose a font - font_dropdown = Window_set_dropdown_button(60,19,104,11,0, Get_item_by_index(&Font_files_list,selected_font)->Short_name,1,0,1,RIGHT_SIDE|LEFT_SIDE); // 5 + font_dropdown = Window_set_dropdown_button(172, 43, 104, 11, 0, Get_item_by_index(&Font_files_list,selected_font)->Short_name,1,0,1,RIGHT_SIDE|LEFT_SIDE); // 5 for (temp=0; tempShort_name); // Cancel - Window_set_normal_button(227, 120, 51,14,"Cancel",0,1,SDLK_ESCAPE); // 6 + Window_set_normal_button(61, 120, 51,14,"Cancel",0,1,SDLK_ESCAPE); // 6 // Dropdown list to choose cursor type - cursor_dropdown = Window_set_dropdown_button(60, 34, 104, 11, 0, + cursor_dropdown = Window_set_dropdown_button(172, 69, 104, 11, 0, cursors[selected_cursor], 1, 0, 1, RIGHT_SIDE|LEFT_SIDE); // 7 for (temp = 0; temp<3; temp++) Window_dropdown_add_item(cursor_dropdown, temp, cursors[temp]); - Window_set_normal_button(172, 23, 14, 14, + Window_set_normal_button(172, 87, 14, 14, (Config.Display_image_limits)?"X":" ", -1, 1, SDLK_LAST); // 8 - Print_in_window( 190, 21,"Draw picture", MC_Dark, MC_Light); - Print_in_window( 190, 30,"limits", MC_Dark, MC_Light); + Print_in_window( 190, 85,"Draw picture", MC_Dark, MC_Light); + Print_in_window( 190, 94,"limits", MC_Dark, MC_Light); - Window_set_normal_button(172, 52, 14, 14, + Window_set_normal_button(172, 111, 14, 14, (Config.Separate_colors)?"X":" ", -1, 1, SDLK_LAST); // 9 - Print_in_window( 190, 50,"Separate", MC_Dark, MC_Light); - Print_in_window( 190, 59,"colors", MC_Dark, MC_Light); + Print_in_window( 190, 109,"Separate", MC_Dark, MC_Light); + Print_in_window( 190, 118,"colors", MC_Dark, MC_Light); Window_redraw_list(skin_list); + for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++) + for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++) + Pixel_in_window(x, y, skin_logo[offs_y][x_pos]); + Update_window_area(0,0,Window_width, Window_height); Display_cursor(); @@ -1110,6 +1117,22 @@ void Button_Skins(void) case 3 : // doesn't happen break; case 4 : // a file is selected + + // (Re-)load GUI graphics from selected skins + strcpy(skinsdir, Get_item_by_index(&Skin_files_list, + skin_list->List_start + skin_list->Cursor_position)->Full_name); + gfx = Load_graphics(skinsdir); + if (gfx == NULL) // Error + { + Verbose_error_message(Gui_loading_error_message); + } + + // Update preview + for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++) + for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++) + Pixel_in_window(x, y, skin_logo[offs_y][x_pos]); + Update_window_area(4, 14, 174, 16); + break; case 5 : // Font dropdown selected_font = Window_attribute2; // Get the index of the chosen font. @@ -1117,36 +1140,28 @@ void Button_Skins(void) // 6: Cancel case 7 : // Cursor selected_cursor = Window_attribute2; - break; + break; case 8: // Display limits showlimits = !showlimits; Hide_cursor(); - Print_in_window(175, 26, (showlimits)?"X":" ", MC_Black, MC_Light); + Print_in_window(175, 90, (showlimits)?"X":" ", MC_Black, MC_Light); Display_cursor(); break; case 9: // Separate colors separatecolors = !separatecolors; Hide_cursor(); - Print_in_window(175, 55, (separatecolors)?"X":" ", MC_Black, MC_Light); + Print_in_window(175, 114, (separatecolors)?"X":" ", MC_Black, MC_Light); Display_cursor(); break; - } + } } while ( (clicked_button!=1) && (clicked_button !=6) && (Key != SDLK_ESCAPE)); if(clicked_button == 1) { - T_Gui_skin * gfx; - byte * new_font; + byte * new_font; - // (Re-)load GUI graphics from selected skins - strcpy(skinsdir, Get_item_by_index(&Skin_files_list, skin_list->List_start+skin_list->Cursor_position)->Full_name); - gfx=Load_graphics(skinsdir); - if (gfx == NULL) // Error - { - Verbose_error_message(Gui_loading_error_message); - } - else + if (gfx != NULL) { free(Gfx); Gfx = gfx; diff --git a/global.h b/global.h index b2eef28d..37a3f6d3 100644 --- a/global.h +++ b/global.h @@ -805,6 +805,9 @@ GFX2_GLOBAL byte * Menu_font; /// Pointer to the current active skin. GFX2_GLOBAL T_Gui_skin * Gfx; +/// Logo of skin +byte skin_logo[16][173]; + // -- Help data /// Index of the ::Help_section shown by the Help screen. diff --git a/init.c b/init.c index 63fe3f31..44de50f4 100644 --- a/init.c +++ b/init.c @@ -346,6 +346,12 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) return 1; if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->Menu_block, MENU_WIDTH, MENU_HEIGHT,"menu",0)) return 1; + + cursor_x += MENU_WIDTH; + if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "logo")) + return 1; + if (Read_GUI_block(gui, cursor_x, cursor_y, skin_logo, 173, 16, "logo", 0)) + return 1; cursor_y+=MENU_HEIGHT; // Effets diff --git a/skins/skin_classic.png b/skins/skin_classic.png index 6ce4c0242df329b00125dbb4f38ba73843b89352..76554ce5214d50953019754f785429fcaf291360 100644 GIT binary patch literal 14069 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 O=xFFa_@-w4^8W!+luT6s delta 13615 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ᔟt#~t?0KP+oG-%kaK8RKJGhzWZ|k4=6J;Vdf}VY~ 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%0D=Qr^vY9XutUMkFYAisaE`Wrq=35D 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 Rb?x$_s`y%=T+S@u{{gm5G3fvR delta 15834 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 kvUQ99PCowsDE2@zV Date: Fri, 30 Oct 2009 19:23:24 +0000 Subject: [PATCH 17/30] Added version of the classic skin with remapped colors for testing the skin switcher git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1109 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- skins/skin_remapped.png | Bin 0 -> 14237 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 skins/skin_remapped.png diff --git a/skins/skin_remapped.png b/skins/skin_remapped.png new file mode 100644 index 0000000000000000000000000000000000000000..30a40fed8476858083ec1348eb8aaabf0b7272dd GIT binary patch literal 14237 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 WZ7kFJN53%w=-e^5U8ZRh{{H~uWAD@e literal 0 HcmV?d00001 From d4b730cb4dd2ff62da4407528cd3a6e7d64a20c6 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Fri, 30 Oct 2009 21:56:56 +0000 Subject: [PATCH 18/30] Remap the preview of the skin and use the old colors to draw the list in order to keep the skin changer looking good even if skins use different MC_ indexes. Thingsd are still messed up after loading a skin but I can't find out why this happens and remap does not seem to help. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1110 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- buttons.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/buttons.c b/buttons.c index 5732e5b8..b5f961d4 100644 --- a/buttons.c +++ b/buttons.c @@ -994,6 +994,13 @@ void Add_font_or_skin(const char *name) } +// declared in windows.c for remap +extern byte Old_black; +extern byte Old_dark; +extern byte Old_light; +extern byte Old_white; +extern byte Old_trans; + // Callback to display a skin name in the list void Draw_one_skin_name(word x, word y, word index, byte highlighted) { @@ -1001,8 +1008,9 @@ void Draw_one_skin_name(word x, word y, word index, byte highlighted) if (Skin_files_list.Nb_elements) { - current_item = Get_item_by_index(&Skin_files_list, index); - Print_in_window(x,y,current_item->Short_name, MC_Black, (highlighted)?MC_Dark:MC_Light); + current_item = Get_item_by_index(&Skin_files_list, index); + // We use Old_ colors because previewing a skin mess up MC_ ... + Print_in_window(x,y,current_item->Short_name, Old_black, (highlighted)?Old_dark:Old_light); } } @@ -1104,6 +1112,12 @@ void Button_Skins(void) Display_cursor(); + Old_black = MC_Black; + Old_dark = MC_Dark; + Old_light = MC_Light; + Old_white = MC_White; + Old_trans = MC_Trans; + do { clicked_button=Window_clicked_button(); @@ -1121,6 +1135,7 @@ void Button_Skins(void) // (Re-)load GUI graphics from selected skins strcpy(skinsdir, Get_item_by_index(&Skin_files_list, skin_list->List_start + skin_list->Cursor_position)->Full_name); + gfx = Load_graphics(skinsdir); if (gfx == NULL) // Error { @@ -1128,9 +1143,20 @@ void Button_Skins(void) } // Update preview + // The new palette is not in place but the skin is loaded using the + // new color indexes, so we have to reverse-remap it... for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++) for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++) - Pixel_in_window(x, y, skin_logo[offs_y][x_pos]); + { + if (skin_logo[offs_y][x_pos] == MC_Black) + Pixel_in_window(x, y, Old_black); + else if (skin_logo[offs_y][x_pos] == MC_Dark) + Pixel_in_window(x, y, Old_dark); + else if (skin_logo[offs_y][x_pos] == MC_Light) + Pixel_in_window(x, y, Old_light); + else if (skin_logo[offs_y][x_pos] == MC_White) + Pixel_in_window(x, y, Old_white); + } Update_window_area(4, 14, 174, 16); break; @@ -1185,6 +1211,7 @@ void Button_Skins(void) Config.Cursor = selected_cursor; Config.Display_image_limits = showlimits; Config.Separate_colors = separatecolors; + } Close_window(); From f9dc259af5b006b22f23ffc3f1013512c94c1424 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 31 Oct 2009 09:36:35 +0000 Subject: [PATCH 19/30] -Update Doxyfile for newer doxygen version -Fix some problems with doxygen comments -Regenerate doxygen documentation git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1111 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- Doxyfile | 14 +------------- const.h | 4 ++-- engine.c | 2 +- filesel.h | 2 +- windows.c | 2 +- 5 files changed, 6 insertions(+), 18 deletions(-) diff --git a/Doxyfile b/Doxyfile index ad374f7e..4a4a3ba5 100644 --- a/Doxyfile +++ b/Doxyfile @@ -939,20 +939,8 @@ ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. -# If the tag value is set to FRAME, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. Other possible values -# for this tag are: HIERARCHIES, which will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list; -# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which -# disables this behavior completely. For backwards compatibility with previous -# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE -# respectively. -GENERATE_TREEVIEW = FRAME +GENERATE_TREEVIEW = YES # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree diff --git a/const.h b/const.h index 4cfd3829..01a5df4c 100644 --- a/const.h +++ b/const.h @@ -241,8 +241,8 @@ enum CHUNKS_CFG /// Identifiers for the 8x8 icons of ::Gfx->Icon_sprite (most are unused now) enum ICON_TYPES { - ICON_FLOPPY_3_5=0, ///< 3½" Floppy disk - ICON_FLOPPY_5_25, ///< 5¼" Floppy disk + ICON_FLOPPY_3_5=0, ///< 3.5 Floppy disk + ICON_FLOPPY_5_25, ///< 5.25 Floppy disk ICON_HDD, ///< Hard disk drive ICON_CDROM, ///< CD-ROM ICON_NETWORK, ///< "Network" drive diff --git a/engine.c b/engine.c index 63c86154..d97230a5 100644 --- a/engine.c +++ b/engine.c @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with Grafx2; if not, see */ -/// @file Window engine and interface management +/// @file engine.c: Window engine and interface management #include #include #include diff --git a/filesel.h b/filesel.h index 0ad4520a..ba2cc4a5 100644 --- a/filesel.h +++ b/filesel.h @@ -32,7 +32,7 @@ void Add_element_to_list(T_Fileselector *list, const char * fname, int type); /// /// Formats a display name for a file, directory, or similar name (drive, volume). /// The returned value is a pointer to a single static buffer of 19 characters -/// including the '\0'. +/// including the '\\0'. char * Format_filename(const char * fname, int type); void Free_fileselector_list(T_Fileselector *list); diff --git a/windows.c b/windows.c index 8f0f311d..7cbb6f02 100644 --- a/windows.c +++ b/windows.c @@ -213,7 +213,7 @@ void Set_back_color(byte color) /// /// Redraw the cell in the menu palette for ::Fore_color. /// This function checks bounds, it won't draw anything if Fore_color is not visible. -/// @param id:Color number to frame +/// @param id: Color number to frame void Frame_menu_color(byte id) { word start_x,start_y,end_x,end_y; From a2fd796e59f0ac1b57a7d5e2a55021b23116cd65 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 31 Oct 2009 10:44:09 +0000 Subject: [PATCH 20/30] Proper remapping on skin change in (almost) all cases. I commit this before breaking everything trying to fix the remaining issue... git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1114 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- buttons.c | 37 +++++++++++++++++++++++++++++++------ windows.c | 24 ++++++++++++++++++------ windows.h | 1 + 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/buttons.c b/buttons.c index b5f961d4..4d7a101a 100644 --- a/buttons.c +++ b/buttons.c @@ -1014,6 +1014,11 @@ void Draw_one_skin_name(word x, word y, word index, byte highlighted) } } +#define SWAP_BYTES(a,b) { byte c=a; a=b; b=c;} +#define SWAP_WORDS(a,b) { word c=a; a=b; b=c;} +#define SWAP_SHORTS(a,b) { short c=a; a=b; b=c;} +#define SWAP_FLOATS(a,b) { float c=a; a=b; b=c;} + /// Skin selector window void Button_Skins(void) { @@ -1108,7 +1113,7 @@ void Button_Skins(void) for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++) Pixel_in_window(x, y, skin_logo[offs_y][x_pos]); - Update_window_area(0,0,Window_width, Window_height); + Update_window_area(0, 0, Window_width, Window_height); Display_cursor(); @@ -1212,6 +1217,31 @@ void Button_Skins(void) Config.Display_image_limits = showlimits; Config.Separate_colors = separatecolors; + // We loaded a new menu but not changed the palette + // So we have to remap FROM MC_ TO Old_ and not the reverse way... + SWAP_BYTES(Old_black, MC_Black); + SWAP_BYTES(Old_dark, MC_Dark); + SWAP_BYTES(Old_light, MC_Light); + SWAP_BYTES(Old_white, MC_White); + SWAP_BYTES(Old_trans, MC_Trans); + Remap_menu_sprites(); + Old_black = MC_Black; + Old_dark = MC_Dark; + Old_light = MC_Light; + Old_white = MC_White; + Old_trans = MC_Trans; + + } else { + MC_Black = Old_black; + MC_Dark = Old_dark; + MC_Light = Old_light; + MC_White = Old_white; + MC_Trans = Old_trans; + + // TODO : il faudrait aussi restaurer la preview du skin initial, soit ici + // soit la prochaine fois qu'on ouvre la fenêtre. Une solution est de + // ne pas utiliser une variable globale pour skin_logo mais de la mettre + // dans gfx à la place. } Close_window(); @@ -1228,11 +1258,6 @@ void Button_Page(void) byte factor_index; char Temp_buffer[256]; - #define SWAP_BYTES(a,b) { byte c=a; a=b; b=c;} - #define SWAP_WORDS(a,b) { word c=a; a=b; b=c;} - #define SWAP_SHORTS(a,b) { short c=a; a=b; b=c;} - #define SWAP_FLOATS(a,b) { float c=a; a=b; b=c;} - Hide_cursor(); // On dégrossit le travail avec les infos des listes de pages diff --git a/windows.c b/windows.c index 7cbb6f02..00577a7b 100644 --- a/windows.c +++ b/windows.c @@ -2543,14 +2543,14 @@ void Remap_screen_after_menu_colors_change(void) void Compute_optimal_menu_colors(T_Components * palette) { byte table[4]; - short i,j,k; + short i; Old_black =MC_Black; - Old_dark=MC_Dark; - Old_light=MC_Light; - Old_white=MC_White; - Old_trans=MC_Trans; + Old_dark = MC_Dark; + Old_light = MC_Light; + Old_white = MC_White; + Old_trans = MC_Trans; // Recherche du noir Compute_4_best_colors_for_1_menu_color @@ -2610,7 +2610,14 @@ void Compute_optimal_menu_colors(T_Components * palette) for (MC_Trans=0; ((MC_Trans==MC_Black) || (MC_Trans==MC_Dark) || (MC_Trans==MC_Light) || (MC_Trans==MC_White)); MC_Trans++); - // Et maintenant, on "remappe" tous les sprites, etc... + Remap_menu_sprites(); +} + +/// Remap all menu data when the palette changes or a new skin is loaded +void Remap_menu_sprites() +{ + int i, j, k; + if ( (MC_Light!=Old_light) || (MC_Dark!=Old_dark) || (MC_White!=Old_white) @@ -2667,6 +2674,11 @@ void Compute_optimal_menu_colors(T_Components * palette) for (j=0; jIcon_sprite[k][j][i]); + + // Skin preview + for (j = 0; j < 173; j++) + for (i = 0; i < 16; i++) + Remap_pixel(&skin_logo[i][j]); } Clear_border(MC_Black); } diff --git a/windows.h b/windows.h index a612807f..84563728 100644 --- a/windows.h +++ b/windows.h @@ -39,6 +39,7 @@ void Hide_cursor(void); void Remap_screen_after_menu_colors_change(void); void Compute_optimal_menu_colors(T_Components * palette); +void Remap_menu_sprites(); void Position_screen_according_to_zoom(void); void Compute_separator_data(void); From 2b02ff505f37cb731e93c0c6a2f6586018a084a1 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 31 Oct 2009 11:19:44 +0000 Subject: [PATCH 21/30] Moved skin preview to the Gfx struct so it is not overwritten if you cancel skin loading. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1115 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- buttons.c | 10 +++++----- global.h | 3 --- init.c | 2 +- op_c.c | 2 +- struct.h | 4 ++++ windows.c | 2 +- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/buttons.c b/buttons.c index 4d7a101a..b06925a8 100644 --- a/buttons.c +++ b/buttons.c @@ -1111,7 +1111,7 @@ void Button_Skins(void) for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++) for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++) - Pixel_in_window(x, y, skin_logo[offs_y][x_pos]); + Pixel_in_window(x, y, Gfx->preview[offs_y][x_pos]); Update_window_area(0, 0, Window_width, Window_height); @@ -1153,13 +1153,13 @@ void Button_Skins(void) for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++) for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++) { - if (skin_logo[offs_y][x_pos] == MC_Black) + if (gfx->preview[offs_y][x_pos] == MC_Black) Pixel_in_window(x, y, Old_black); - else if (skin_logo[offs_y][x_pos] == MC_Dark) + else if (gfx->preview[offs_y][x_pos] == MC_Dark) Pixel_in_window(x, y, Old_dark); - else if (skin_logo[offs_y][x_pos] == MC_Light) + else if (gfx->preview[offs_y][x_pos] == MC_Light) Pixel_in_window(x, y, Old_light); - else if (skin_logo[offs_y][x_pos] == MC_White) + else if (gfx->preview[offs_y][x_pos] == MC_White) Pixel_in_window(x, y, Old_white); } Update_window_area(4, 14, 174, 16); diff --git a/global.h b/global.h index 37a3f6d3..b2eef28d 100644 --- a/global.h +++ b/global.h @@ -805,9 +805,6 @@ GFX2_GLOBAL byte * Menu_font; /// Pointer to the current active skin. GFX2_GLOBAL T_Gui_skin * Gfx; -/// Logo of skin -byte skin_logo[16][173]; - // -- Help data /// Index of the ::Help_section shown by the Help screen. diff --git a/init.c b/init.c index 44de50f4..cffa297a 100644 --- a/init.c +++ b/init.c @@ -350,7 +350,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) cursor_x += MENU_WIDTH; if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "logo")) return 1; - if (Read_GUI_block(gui, cursor_x, cursor_y, skin_logo, 173, 16, "logo", 0)) + if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->preview, 173, 16, "logo", 0)) return 1; cursor_y+=MENU_HEIGHT; diff --git a/op_c.c b/op_c.c index e0d28767..1417a623 100644 --- a/op_c.c +++ b/op_c.c @@ -1206,7 +1206,7 @@ void Convert_24b_bitmap_to_256_Floyd_Steinberg(T_Bitmap256 dest,T_Bitmap24B sour } void Convert_24b_bitmap_to_256_nearest_neighbor(T_Bitmap256 dest, - T_Bitmap24B source, int width, int height, T_Components * palette, + T_Bitmap24B source, int width, int height, __attribute__((unused)) T_Components * palette, T_Conversion_table * tc) { T_Bitmap24B current; diff --git a/struct.h b/struct.h index 5b03f0f2..81502a07 100644 --- a/struct.h +++ b/struct.h @@ -426,6 +426,10 @@ typedef struct /// A default 256-color palette. T_Palette Default_palette; + /// Preview for displaying in the skin dialog + byte preview[16][173]; + + } T_Gui_skin; diff --git a/windows.c b/windows.c index 00577a7b..9ed71284 100644 --- a/windows.c +++ b/windows.c @@ -2678,7 +2678,7 @@ void Remap_menu_sprites() // Skin preview for (j = 0; j < 173; j++) for (i = 0; i < 16; i++) - Remap_pixel(&skin_logo[i][j]); + Remap_pixel(&Gfx->preview[i][j]); } Clear_border(MC_Black); } From 49cce9643e99c14b027fe8142dc235ba51d24322 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 31 Oct 2009 12:10:07 +0000 Subject: [PATCH 22/30] Load the favorite colors from the skin, not the ini file. We may want to override them, but for now just change the skin's palette. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1116 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- buttons.c | 36 ++++++++++++------------------------ init.c | 4 ++++ main.c | 9 +++++---- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/buttons.c b/buttons.c index b06925a8..bee902c2 100644 --- a/buttons.c +++ b/buttons.c @@ -1057,6 +1057,14 @@ void Button_Skins(void) Sort_list_of_files(&Font_files_list); selected_font = Find_file_in_fileselector(&Font_files_list, Config.Font_file); + + // Do this before setting up the skin list because it will redraw itself using the old colors... + Old_black = MC_Black; + Old_dark = MC_Dark; + Old_light = MC_Light; + Old_white = MC_White; + Old_trans = MC_Trans; + // -------------------------------------------------------------- @@ -1117,12 +1125,6 @@ void Button_Skins(void) Display_cursor(); - Old_black = MC_Black; - Old_dark = MC_Dark; - Old_light = MC_Light; - Old_white = MC_White; - Old_trans = MC_Trans; - do { clicked_button=Window_clicked_button(); @@ -1217,31 +1219,17 @@ void Button_Skins(void) Config.Display_image_limits = showlimits; Config.Separate_colors = separatecolors; - // We loaded a new menu but not changed the palette - // So we have to remap FROM MC_ TO Old_ and not the reverse way... - SWAP_BYTES(Old_black, MC_Black); - SWAP_BYTES(Old_dark, MC_Dark); - SWAP_BYTES(Old_light, MC_Light); - SWAP_BYTES(Old_white, MC_White); - SWAP_BYTES(Old_trans, MC_Trans); - Remap_menu_sprites(); - Old_black = MC_Black; - Old_dark = MC_Dark; - Old_light = MC_Light; - Old_white = MC_White; - Old_trans = MC_Trans; + // Now find the best colors for the new skin in the current palette + // and remap the skin + Compute_optimal_menu_colors(Main_palette); } else { + // Get the initial colors back MC_Black = Old_black; MC_Dark = Old_dark; MC_Light = Old_light; MC_White = Old_white; MC_Trans = Old_trans; - - // TODO : il faudrait aussi restaurer la preview du skin initial, soit ici - // soit la prochaine fois qu'on ouvre la fenêtre. Une solution est de - // ne pas utiliser une variable globale pour skin_logo mais de la mettre - // dans gfx à la place. } Close_window(); diff --git a/init.c b/init.c index cffa297a..db239326 100644 --- a/init.c +++ b/init.c @@ -272,6 +272,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) // Carré "noir" MC_Black = Get_SDL_pixel_8(gui,cursor_x,cursor_y); + Fav_menu_colors[0] = gfx->Default_palette[MC_Black]; do { if (++cursor_x>=gui->w) @@ -283,6 +284,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) } while(color==MC_Black); // Carré "foncé" MC_Dark=color; + Fav_menu_colors[1] = gfx->Default_palette[MC_Dark]; do { if (++cursor_x>=gui->w) @@ -294,6 +296,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) } while(color==MC_Dark); // Carré "clair" MC_Light=color; + Fav_menu_colors[2] = gfx->Default_palette[MC_Light]; do { if (++cursor_x>gui->w) @@ -305,6 +308,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) } while(color==MC_Light); // Carré "blanc" MC_White=color; + Fav_menu_colors[3] = gfx->Default_palette[MC_White]; do { if (++cursor_x>=gui->w) diff --git a/main.c b/main.c index ecb63bb8..34c76392 100644 --- a/main.c +++ b/main.c @@ -568,10 +568,11 @@ int Init_program(int argc,char * argv[]) // Transfert des valeurs du .INI qui ne changent pas dans des variables // plus accessibles: - Gfx->Default_palette[MC_Black]=Fav_menu_colors[0]=Config.Fav_menu_colors[0]; - Gfx->Default_palette[MC_Dark] =Fav_menu_colors[1]=Config.Fav_menu_colors[1]; - Gfx->Default_palette[MC_Light]=Fav_menu_colors[2]=Config.Fav_menu_colors[2]; - Gfx->Default_palette[MC_White]=Fav_menu_colors[3]=Config.Fav_menu_colors[3]; + // Let's load the colors from the skin instead ! + // Gfx->Default_palette[MC_Black]=Fav_menu_colors[0]=Config.Fav_menu_colors[0]; + // Gfx->Default_palette[MC_Dark] =Fav_menu_colors[1]=Config.Fav_menu_colors[1]; + // Gfx->Default_palette[MC_Light]=Fav_menu_colors[2]=Config.Fav_menu_colors[2]; + // Gfx->Default_palette[MC_White]=Fav_menu_colors[3]=Config.Fav_menu_colors[3]; Compute_optimal_menu_colors(Gfx->Default_palette); Fore_color=MC_White; Back_color=MC_Black; From 8114cae1e987355db44b5ac00d64655d250c2289 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 31 Oct 2009 13:01:56 +0000 Subject: [PATCH 23/30] Added (r,g,b)=getcolor(c) to lua binding. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1118 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- factory.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/factory.c b/factory.c index 6c6e068c..616d942b 100644 --- a/factory.c +++ b/factory.c @@ -102,6 +102,17 @@ int L_SetColor(lua_State* L) return 0; } +int L_GetColor(lua_state* L) +{ + T_Components couleur; + couleur = Main_palette[lua_tonumber(L,1)]; + + lua_pushinteger(L, couleur.R); + lua_pushinteger(L, couleur.G); + lua_pushinteger(L, couleur.B); + return 3; +} + int L_BrushEnable(lua_State* L) { Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH); @@ -144,6 +155,7 @@ void Button_Brush_Factory(void) lua_register(L,"getbrushsize",L_GetBrushSize); lua_register(L,"getpicturesize",L_GetPictureSize); lua_register(L,"setcolor",L_SetColor); + lua_register(L,"getcolor",L_GetColor); lua_register(L,"brushenable",L_BrushEnable); // For debug only From 71055664331c4aed87359b50fffddf06844d0beb Mon Sep 17 00:00:00 2001 From: Yves Rizoud Date: Sat, 31 Oct 2009 13:50:55 +0000 Subject: [PATCH 24/30] Compilation fixes: A typo, and a cast double->int git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1119 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- factory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/factory.c b/factory.c index 616d942b..e781fce7 100644 --- a/factory.c +++ b/factory.c @@ -102,10 +102,10 @@ int L_SetColor(lua_State* L) return 0; } -int L_GetColor(lua_state* L) +int L_GetColor(lua_State* L) { T_Components couleur; - couleur = Main_palette[lua_tonumber(L,1)]; + couleur = Main_palette[(int)(lua_tonumber(L,1))]; lua_pushinteger(L, couleur.R); lua_pushinteger(L, couleur.G); From 1a2ac678e087ffc16fdcaa77e8c66d03b5df077e Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 31 Oct 2009 15:20:44 +0000 Subject: [PATCH 25/30] Splitted loadsave.c : - loadsave.c : common things - fileformats.c : format that make a full backup of any picture without palette loss - miscfileformats.c : formats that are not saving all the picture (palette only, pixels only, constrained palette) I was not very precise in the splitting and we may rethink the flags that mark if a picture is fully saved or not... it was not updated after we decided to allow the full palette range 0.255 instead of 0.63, so most of the atari format were marked as saving everything. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1120 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- Makefile | 2 +- fileformats.c | 3496 ++++++++++++++++++++++++++ loadsave.c | 6131 +-------------------------------------------- loadsave.h | 35 +- miscfileformats.c | 2485 ++++++++++++++++++ 5 files changed, 6026 insertions(+), 6123 deletions(-) create mode 100644 fileformats.c create mode 100644 miscfileformats.c diff --git a/Makefile b/Makefile index f3e7bc5d..cf0e13f3 100644 --- a/Makefile +++ b/Makefile @@ -279,7 +279,7 @@ endif .PHONY : all debug release clean depend zip version force install uninstall # This is the list of the objects we want to build. Dependancies are built by "make depend" automatically. -OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) +OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o SKIN_FILES = skins/skin_classic.png skins/skin_modern.png skins/font_Classic.png skins/font_Fun.png diff --git a/fileformats.c b/fileformats.c new file mode 100644 index 00000000..5e8052da --- /dev/null +++ b/fileformats.c @@ -0,0 +1,3496 @@ +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2009 Petter Lindquist + Copyright 2008 Yves Rizoud + Copyright 2008 Franck Charlet + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +///@file fileformats.c +/// Saving and loading different picture formats. + +#ifndef __no_pnglib__ +#include +#endif + +#include "errors.h" +#include "global.h" +#include "loadsave.h" +#include "misc.h" +#include "struct.h" + +//////////////////////////////////// IMG //////////////////////////////////// + +// -- Tester si un fichier est au format IMG -------------------------------- +void Test_IMG(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + T_IMG_Header IMG_header; + byte signature[6]={0x01,0x00,0x47,0x12,0x6D,0xB0}; + + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Lecture et vérification de la signature + if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header))) + { + if ( (!memcmp(IMG_header.Filler1,signature,6)) + && IMG_header.Width && IMG_header.Height) + File_error=0; + } + // Fermeture du fichier + fclose(file); + } +} + + +// -- Lire un fichier au format IMG ----------------------------------------- +void Load_IMG(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + byte * buffer; + FILE *file; + word x_pos,y_pos; + long width_read; + long file_size; + T_IMG_Header IMG_header; + + Get_full_filename(filename,0); + File_error=0; + + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + + if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header))) + { + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + IMG_header.Width = SDL_Swap16(IMG_header.Width); + IMG_header.Height = SDL_Swap16(IMG_header.Height); +#endif + + buffer=(byte *)malloc(IMG_header.Width); + + Init_preview(IMG_header.Width,IMG_header.Height,file_size,FORMAT_IMG,PIXEL_SIMPLE); + if (File_error==0) + { + memcpy(Main_palette,IMG_header.Palette,sizeof(T_Palette)); + Set_palette(Main_palette); + Remap_fileselector(); + + Main_image_width=IMG_header.Width; + Main_image_height=IMG_header.Height; + width_read=IMG_header.Width; + + for (y_pos=0;(y_pos=0)?temp:0; + } + if ((i-7)&2) + { + temp=Main_palette[j].G-16; + Main_palette[color].G=(temp>=0)?temp:0; + } + if ((i-7)&4) + { + temp=Main_palette[j].B-16; + Main_palette[color].B=(temp>=0)?temp:0; + } + } + } + } + // Ici, il reste les 16 dernières couleurs à modifier + for (i=240,j=0; j<16; i++,j++) + { + temp=Main_palette[j].R+8; + Main_palette[i].R=(temp<63)?temp:63; + temp=Main_palette[j].G+8; + Main_palette[i].G=(temp<63)?temp:63; + temp=Main_palette[j].B+8; + Main_palette[i].B=(temp<63)?temp:63; + } + } + else if (Image_HAM==8) + { + for (i=1; i<=3; i++) + { + // On recopie la palette de base + memcpy(Main_palette+(i<<6),Main_palette,192); + // On modifie les teintes de cette palette + for (j=0; j<64; j++) + { + color=(i<<6)+j; + switch (i) + { + case 1 : + temp=Main_palette[j].R+16; + Main_palette[color].R=(temp<63)?temp:63; + break; + case 2 : + temp=Main_palette[j].G+16; + Main_palette[color].G=(temp<63)?temp:63; + break; + default: + temp=Main_palette[j].B+16; + Main_palette[color].B=(temp<63)?temp:63; + } + } + } + } + else // Image 64 couleurs sauvée en 32. + { + for (i=0; i<32; i++) + { + j=i+32; + Main_palette[j].R=Main_palette[i].R>>1; + Main_palette[j].G=Main_palette[i].G>>1; + Main_palette[j].B=Main_palette[i].B>>1; + } + } + } + + // ------------------------- Attendre une section ------------------------- + byte Wait_for(byte * expected_section) + { + // Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur) + dword Taille_section; + byte section_read[4]; + + if (! Read_bytes(LBM_file,section_read,4)) + return 0; + while (memcmp(section_read,expected_section,4)) // Sect. pas encore trouvée + { + if (!Read_dword_be(LBM_file,&Taille_section)) + return 0; + if (Taille_section&1) + Taille_section++; + if (fseek(LBM_file,Taille_section,SEEK_CUR)) + return 0; + if (! Read_bytes(LBM_file,section_read,4)) + return 0; + } + return 1; + } + +// Les images ILBM sont stockés en bitplanes donc on doit trifouiller les bits pour +// en faire du chunky + +byte Color_ILBM_line(word x_pos, word real_line_size, byte HBPm1) +{ + // Renvoie la couleur du pixel (ILBM) en x_pos. + // CL sera le rang auquel on extrait les bits de la couleur + byte cl = 7 - (x_pos & 7); + int ax,bh,dx; + byte bl=0; + + for(dx=HBPm1;dx>=0;dx--) + { + //CIL_Loop + ax = (real_line_size * dx + x_pos) >> 3; + bh = (LBM_buffer[ax] >> cl) & 1; + + bl = (bl << 1) + bh; + } + + return bl; +} + +byte HBPm1; // header.BitPlanes-1 + + // ----------------------- Afficher une ligne ILBM ------------------------ + void Draw_ILBM_line(short y_pos, short real_line_size) + { + byte color; + byte red,green,blue; + byte temp; + short x_pos; + + if (Image_HAM<=1) // ILBM + { + for (x_pos=0; x_pos>2; + color=Best_color(red,green,blue); + break; + case 0x02: // red + red=temp>>2; + color=Best_color(red,green,blue); + break; + case 0x03: // green + green=temp>>2; + color=Best_color(red,green,blue); + break; + default: // Nouvelle couleur + color=temp; + red=Main_palette[color].R; + green =Main_palette[color].G; + blue =Main_palette[color].B; + } + Pixel_load_function(x_pos,y_pos,color); + } + } + } + + +void Load_LBM(void) +{ + char filename[MAX_PATH_CHARACTERS]; + T_LBM_Header header; + char format[4]; + char section[4]; + byte temp_byte; + short b256; + dword nb_colors; + dword image_size; + short x_pos; + short y_pos; + short counter; + short line_size; // Taille d'une ligne en octets + short real_line_size; // Taille d'une ligne en pixels + byte color; + long file_size; + dword dummy; + + Get_full_filename(filename,0); + + File_error=0; + + if ((LBM_file=fopen(filename, "rb"))) + { + file_size=File_length_file(LBM_file); + + // On avance dans le fichier (pas besoin de tester ce qui l'a déjà été) + Read_bytes(LBM_file,section,4); + Read_dword_be(LBM_file,&dummy); + Read_bytes(LBM_file,format,4); + if (!Wait_for((byte *)"BMHD")) + File_error=1; + Read_dword_be(LBM_file,&dummy); + + // Maintenant on lit le header pour pouvoir commencer le chargement de l'image + if ( (Read_word_be(LBM_file,&header.Width)) + && (Read_word_be(LBM_file,&header.Height)) + && (Read_word_be(LBM_file,&header.X_org)) + && (Read_word_be(LBM_file,&header.Y_org)) + && (Read_byte(LBM_file,&header.BitPlanes)) + && (Read_byte(LBM_file,&header.Mask)) + && (Read_byte(LBM_file,&header.Compression)) + && (Read_byte(LBM_file,&header.Pad1)) + && (Read_word_be(LBM_file,&header.Transp_col)) + && (Read_byte(LBM_file,&header.X_aspect)) + && (Read_byte(LBM_file,&header.Y_aspect)) + && (Read_word_be(LBM_file,&header.X_screen)) + && (Read_word_be(LBM_file,&header.Y_screen)) + && header.Width && header.Height) + { + if ( (header.BitPlanes) && (Wait_for((byte *)"CMAP")) ) + { + Read_dword_be(LBM_file,&nb_colors); + nb_colors/=3; + + if (((dword)1< il faut copier les 32 coul. + } // sur les 32 suivantes et assombrir ces dernières. + else + { + if ((header.BitPlanes==6) || (header.BitPlanes==8)) + Image_HAM=header.BitPlanes; + else + /* File_error=1;*/ /* C'est censé être incorrect mais j'ai */ + Image_HAM=0; /* trouvé un fichier comme ça, alors... */ + } + } + else + Image_HAM=0; + + if ( (!File_error) && (nb_colors>=2) && (nb_colors<=256) ) + { + HBPm1=header.BitPlanes-1; + if (header.Mask==1) + header.BitPlanes++; + + // Deluxe paint le fait... alors on le fait... + Back_color=header.Transp_col; + + // On commence par passer la palette en 256 comme ça, si la nouvelle + // palette a moins de 256 coul, la précédente ne souffrira pas d'un + // assombrissement préjudiciable. + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + else + Palette_64_to_256(Main_palette); + // On peut maintenant charger la nouvelle palette + if (Read_bytes(LBM_file,Main_palette,3*nb_colors)) + { + Palette_256_to_64(Main_palette); + if (Image_HAM) + Adapt_palette_HAM(); + Palette_64_to_256(Main_palette); + Set_palette(Main_palette); + Remap_fileselector(); + + // On lit l'octet de padding du CMAP si la taille est impaire + if (nb_colors&1) + if (Read_byte(LBM_file,&temp_byte)) + File_error=2; + + if ( (Wait_for((byte *)"BODY")) && (!File_error) ) + { + Read_dword_be(LBM_file,&image_size); + //swab((char *)&header.Width ,(char *)&Main_image_width,2); + //swab((char *)&header.Height,(char *)&Main_image_height,2); + Main_image_width = header.Width; + Main_image_height = header.Height; + + //swab((char *)&header.X_screen,(char *)&Original_screen_X,2); + //swab((char *)&header.Y_screen,(char *)&Original_screen_Y,2); + Original_screen_X = header.X_screen; + Original_screen_Y = header.Y_screen; + + Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_LBM,PIXEL_SIMPLE); + if (File_error==0) + { + if (!memcmp(format,"ILBM",4)) // "ILBM": InterLeaved BitMap + { + // Calcul de la taille d'une ligne ILBM (pour les images ayant des dimensions exotiques) + if (Main_image_width & 15) + { + real_line_size=( (Main_image_width+16) >> 4 ) << 4; + line_size=( (Main_image_width+16) >> 4 )*(header.BitPlanes<<1); + } + else + { + real_line_size=Main_image_width; + line_size=(Main_image_width>>3)*header.BitPlanes; + } + + if (!header.Compression) + { // non compressé + LBM_buffer=(byte *)malloc(line_size); + for (y_pos=0; ((y_pos 127 alors il faut répéter 256-'temp_byte' fois la couleur de l'octet suivant + // Si temp_byte <= 127 alors il faut afficher directement les 'temp_byte' octets suivants + if (temp_byte>127) + { + if(Read_byte(LBM_file, &color)!=1) + { + File_error=2; + break; + } + b256=(short)(256-temp_byte); + for (counter=0; counter<=b256; counter++) + if (x_pos=line_size || Read_byte(LBM_file, &(LBM_buffer[x_pos++]))!=1) + File_error=2; + } + if (!File_error) + Draw_ILBM_line(y_pos,real_line_size); + } + + free(LBM_buffer); + /*Close_lecture();*/ + } + } + else // "PBM ": Planar(?) BitMap + { + real_line_size=Main_image_width+(Main_image_width&1); + + if (!header.Compression) + { // non compressé + LBM_buffer=(byte *)malloc(real_line_size); + for (y_pos=0; ((y_pos127) + { + if(Read_byte(LBM_file, &color)!=1) + { + File_error=2; + break; + } + b256=256-temp_byte; + for (counter=0; counter<=b256; counter++) + Pixel_load_function(x_pos++,y_pos,color); + } + else + for (counter=0; counter<=temp_byte; counter++) + { + byte byte_read=0; + if(Read_byte(LBM_file, &byte_read)!=1) + { + File_error=2; + break; + } + Pixel_load_function(x_pos++,y_pos,byte_read); + } + } + } + /*Close_lecture();*/ + } + } + } + } + else + Set_file_error(2); + } + else + { + File_error=1; + } + } + else + Set_file_error(1); + } + else + File_error=1; + } + else + File_error=1; + + fclose(LBM_file); + } + else + File_error=1; +} + + +// -- Sauver un fichier au format LBM --------------------------------------- + + byte LBM_color_list[129]; + word LBM_list_size; + byte LBM_repetition_mode; + + // ------------- Ecrire les couleurs que l'on vient de traiter ------------ + void Transfer_colors(void) + { + byte index; + + if (LBM_list_size>0) + { + if (LBM_repetition_mode) + { + Write_one_byte(LBM_file,257-LBM_list_size); + Write_one_byte(LBM_file,LBM_color_list[0]); + } + else + { + Write_one_byte(LBM_file,LBM_list_size-1); + for (index=0; index et on a 3 couleurs qui se suivent + { + LBM_list_size-=2; + Transfer_colors(); + LBM_color_list[0]=color; + LBM_color_list[1]=color; + LBM_color_list[2]=color; + LBM_list_size=3; + LBM_repetition_mode=1; + } + } + else // La couleur n'est pas la même que la précédente + { + if (!LBM_repetition_mode) // On conserve le mode... + { + LBM_color_list[LBM_list_size++]=color; + if (LBM_list_size==128) + Transfer_colors(); + } + else // On change de mode... + { + Transfer_colors(); + LBM_color_list[LBM_list_size]=color; + LBM_list_size++; + } + } + } + } + + +void Save_LBM(void) +{ + char filename[MAX_PATH_CHARACTERS]; + T_LBM_Header header; + word x_pos; + word y_pos; + byte temp_byte; + word real_width; + int file_size; + + File_error=0; + Get_full_filename(filename,0); + + // Ouverture du fichier + if ((LBM_file=fopen(filename,"wb"))) + { + Write_bytes(LBM_file,"FORM",4); + Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin + + Write_bytes(LBM_file,"PBM BMHD",8); + Write_dword_be(LBM_file,20); + + // On corrige la largeur de l'image pour qu'elle soit multiple de 2 + real_width=Main_image_width+(Main_image_width&1); + + //swab((byte *)&real_width,(byte *)&header.Width,2); + header.Width=Main_image_width; + header.Height=Main_image_height; + header.X_org=0; + header.Y_org=0; + header.BitPlanes=8; + header.Mask=0; + header.Compression=1; + header.Pad1=0; + header.Transp_col=Back_color; + header.X_aspect=1; + header.Y_aspect=1; + header.X_screen = Screen_width; + header.Y_screen = Screen_height; + + Write_word_be(LBM_file,header.Width); + Write_word_be(LBM_file,header.Height); + Write_word_be(LBM_file,header.X_org); + Write_word_be(LBM_file,header.Y_org); + Write_bytes(LBM_file,&header.BitPlanes,1); + Write_bytes(LBM_file,&header.Mask,1); + Write_bytes(LBM_file,&header.Compression,1); + Write_bytes(LBM_file,&header.Pad1,1); + Write_word_be(LBM_file,header.Transp_col); + Write_bytes(LBM_file,&header.X_aspect,1); + Write_bytes(LBM_file,&header.Y_aspect,1); + Write_word_be(LBM_file,header.X_screen); + Write_word_be(LBM_file,header.Y_screen); + + Write_bytes(LBM_file,"CMAP",4); + Write_dword_be(LBM_file,sizeof(T_Palette)); + + Write_bytes(LBM_file,Main_palette,sizeof(T_Palette)); + + Write_bytes(LBM_file,"BODY",4); + Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin + + Init_write_buffer(); + + LBM_list_size=0; + + for (y_pos=0; ((y_pos on efface le fichier + remove(filename); + } + else + File_error=1; +} + + + +//////////////////////////////////// BMP //////////////////////////////////// +#pragma pack(1) +typedef struct +{ + word Signature; // ='BM' = 0x4D42 + dword Size_1; // =Taille du fichier + word Reserved_1; // =0 + word Reserved_2; // =0 + dword Offset; // Nb octets avant les données bitmap + + dword Size_2; // =40 + dword Width; + dword Height; + word Planes; // =1 + word Nb_bits; // =1,4,8 ou 24 + dword Compression; + dword Size_3; + dword XPM; + dword YPM; + dword Nb_Clr; + dword Clr_Imprt; +} T_BMP_Header; +#pragma pack() + +// -- Tester si un fichier est au format BMP -------------------------------- +void Test_BMP(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + T_BMP_Header header; + + File_error=1; + Get_full_filename(filename,0); + + if ((file=fopen(filename, "rb"))) + { + if (Read_bytes(file,&(header.Signature),2) // "BM" + && Read_dword_le(file,&(header.Size_1)) + && Read_word_le(file,&(header.Reserved_1)) + && Read_word_le(file,&(header.Reserved_2)) + && Read_dword_le(file,&(header.Offset)) + && Read_dword_le(file,&(header.Size_2)) + && Read_dword_le(file,&(header.Width)) + && Read_dword_le(file,&(header.Height)) + && Read_word_le(file,&(header.Planes)) + && Read_word_le(file,&(header.Nb_bits)) + && Read_dword_le(file,&(header.Compression)) + && Read_dword_le(file,&(header.Size_3)) + && Read_dword_le(file,&(header.XPM)) + && Read_dword_le(file,&(header.YPM)) + && Read_dword_le(file,&(header.Nb_Clr)) + && Read_dword_le(file,&(header.Clr_Imprt)) + ) + { + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + header.Signature = SDL_Swap16(header.Signature); +#endif + + if ( (header.Signature==0x4D42) && (header.Size_2==40) + && header.Width && header.Height ) + File_error=0; + } + fclose(file); + } +} + +// Find the 8 important bits in a dword +byte Bitmap_mask(dword pixel, dword mask) +{ + byte result; + int i; + int bits_found; + + switch(mask) + { + // Shortcuts to quickly handle the common 24/32bit cases + case 0x000000FF: + return (pixel & 0x000000FF); + case 0x0000FF00: + return (pixel & 0x0000FF00)>>8; + case 0x00FF0000: + return (pixel & 0x00FF0000)>>16; + case 0xFF000000: + return (pixel & 0xFF000000)>>24; + } + // Uncommon : do it bit by bit. + bits_found=0; + result=0; + // Process the mask from low to high bit + for (i=0;i<32;i++) + { + // Found a bit in the mask + if (mask & (1<=8) + return result; + } + } + // Less than 8 bits in the mask: scale the result to 8 bits + return result << (8-bits_found); +} + +// -- Charger un fichier au format BMP -------------------------------------- +void Load_BMP(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + T_BMP_Header header; + byte * buffer; + word index; + byte local_palette[256][4]; // R,G,B,0 + word nb_colors = 0; + short x_pos; + short y_pos; + word line_size; + byte a,b,c=0; + long file_size; + + Get_full_filename(filename,0); + + File_error=0; + + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + + if (Read_word_le(file,&(header.Signature)) + && Read_dword_le(file,&(header.Size_1)) + && Read_word_le(file,&(header.Reserved_1)) + && Read_word_le(file,&(header.Reserved_2)) + && Read_dword_le(file,&(header.Offset)) + && Read_dword_le(file,&(header.Size_2)) + && Read_dword_le(file,&(header.Width)) + && Read_dword_le(file,&(header.Height)) + && Read_word_le(file,&(header.Planes)) + && Read_word_le(file,&(header.Nb_bits)) + && Read_dword_le(file,&(header.Compression)) + && Read_dword_le(file,&(header.Size_3)) + && Read_dword_le(file,&(header.XPM)) + && Read_dword_le(file,&(header.YPM)) + && Read_dword_le(file,&(header.Nb_Clr)) + && Read_dword_le(file,&(header.Clr_Imprt)) + ) + { + switch (header.Nb_bits) + { + case 1 : + case 4 : + case 8 : + if (header.Nb_Clr) + nb_colors=header.Nb_Clr; + else + nb_colors=1<>3; + + buffer=(byte *)malloc(line_size); + for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) + { + if (Read_bytes(file,buffer,line_size)) + for (x_pos=0; x_pos>1] & 0xF); + else + Pixel_load_function(x_pos,y_pos,buffer[x_pos>>1] >> 4 ); + break; + case 1 : + if ( buffer[x_pos>>3] & (0x80>>(x_pos&7)) ) + Pixel_load_function(x_pos,y_pos,1); + else + Pixel_load_function(x_pos,y_pos,0); + } + else + File_error=2; + } + free(buffer); + break; + + case 1 : // Compression RLE 8 bits + x_pos=0; + y_pos=Main_image_height-1; + + /*Init_lecture();*/ + if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) + File_error=2; + while (!File_error) + { + if (a) // Encoded mode + for (index=1; index<=a; index++) + Pixel_load_function(x_pos++,y_pos,b); + else // Absolute mode + switch (b) + { + case 0 : // End of line + x_pos=0; + y_pos--; + break; + case 1 : // End of bitmap + break; + case 2 : // Delta + if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) + File_error=2; + x_pos+=a; + y_pos-=b; + break; + default: // Nouvelle série + while (b) + { + if(Read_byte(file, &a)!=1) + File_error=2; + //Read_one_byte(file, &c); + Pixel_load_function(x_pos++,y_pos,a); + //if (--c) + //{ + // Pixel_load_function(x_pos++,y_pos,c); + // b--; + //} + b--; + } + if (ftell(file) & 1) fseek(file, 1, SEEK_CUR); + } + if (a==0 && b==1) + break; + if(Read_byte(file, &a) !=1 || Read_byte(file, &b)!=1) + { + File_error=2; + } + } + /*Close_lecture();*/ + break; + + case 2 : // Compression RLE 4 bits + x_pos=0; + y_pos=Main_image_height-1; + + /*Init_lecture();*/ + if(Read_byte(file, &a)!=1 || Read_byte(file, &b) != 1) + File_error =2; + while ( (!File_error) && ((a)||(b!=1)) ) + { + if (a) // Encoded mode (A fois les 1/2 pixels de B) + for (index=1; index<=a; index++) + { + if (index & 1) + Pixel_load_function(x_pos,y_pos,b>>4); + else + Pixel_load_function(x_pos,y_pos,b&0xF); + x_pos++; + } + else // Absolute mode + switch (b) + { + case 0 : //End of line + x_pos=0; + y_pos--; + break; + case 1 : // End of bitmap + break; + case 2 : // Delta + if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) + File_error=2; + x_pos+=a; + y_pos-=b; + break; + default: // Nouvelle série (B 1/2 pixels bruts) + for (index=1; ((index<=b) && (!File_error)); index++,x_pos++) + { + if (index&1) + { + if(Read_byte(file, &c)!=1) File_error=2; + Pixel_load_function(x_pos,y_pos,c>>4); + } + else + Pixel_load_function(x_pos,y_pos,c&0xF); + } + // On lit l'octet rendant le nombre d'octets pair, si + // nécessaire. Encore un truc de crétin "made in MS". + if ( ((b&3)==1) || ((b&3)==2) ) + { + byte dummy; + if(Read_byte(file, &dummy)!=1) File_error=2; + } + } + if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) File_error=2; + } + /*Close_lecture();*/ + } + fclose(file); + } + else + { + fclose(file); + File_error=1; + } + } + } + else + { + // Image 16/24/32 bits + dword red_mask; + dword green_mask; + dword blue_mask; + if (header.Nb_bits == 16) + { + red_mask = 0x00007C00; + green_mask = 0x000003E0; + blue_mask = 0x0000001F; + } + else + { + red_mask = 0x00FF0000; + green_mask = 0x0000FF00; + blue_mask = 0x000000FF; + } + File_error=0; + + Main_image_width=header.Width; + Main_image_height=header.Height; + Init_preview_24b(header.Width,header.Height,file_size,FORMAT_BMP); + if (File_error==0) + { + switch (header.Compression) + { + case 3: // BI_BITFIELDS + if (!Read_dword_le(file,&red_mask) || + !Read_dword_le(file,&green_mask) || + !Read_dword_le(file,&blue_mask)) + File_error=2; + break; + default: + break; + } + if (fseek(file, header.Offset, SEEK_SET)) + File_error=2; + } + if (File_error==0) + { + switch (header.Nb_bits) + { + // 24bit bitmap + default: + case 24: + line_size=Main_image_width*3; + x_pos=(line_size % 4); // x_pos sert de variable temporaire + if (x_pos>0) + line_size+=(4-x_pos); + + buffer=(byte *)malloc(line_size); + for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) + { + if (Read_bytes(file,buffer,line_size)) + for (x_pos=0,index=0; x_pos=0) && (!File_error)); y_pos--) + { + if (Read_bytes(file,buffer,line_size)) + for (x_pos=0; x_pos=0) && (!File_error)); y_pos--) + { + if (Read_bytes(file,buffer,line_size)) + for (x_pos=0; x_pos> 3)+1) << 3; + else + line_size=Main_image_width; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + header.Signature = 0x424D; +#else + header.Signature = 0x4D42; +#endif + header.Size_1 =(line_size*Main_image_height)+1078; + header.Reserved_1 =0; + header.Reserved_2 =0; + header.Offset =1078; + header.Size_2 =40; + header.Width =Main_image_width; + header.Height =Main_image_height; + header.Planes =1; + header.Nb_bits =8; + header.Compression=0; + header.Size_3 =0; + header.XPM =0; + header.YPM =0; + header.Nb_Clr =0; + header.Clr_Imprt =0; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + header.Size_1 = SDL_Swap32( header.Size_1 ); + header.Offset = SDL_Swap32( header.Offset ); + header.Size_2 = SDL_Swap32( header.Size_2 ); + header.Width = SDL_Swap32( header.Width ); + header.Height = SDL_Swap32( header.Height ); + header.Planes = SDL_Swap16( header.Planes ); + header.Nb_bits = SDL_Swap16( header.Nb_bits ); + // If you ever set any more fields to non-zero, please swap here! +#endif + + if (Write_bytes(file,&header,sizeof(T_BMP_Header))) + { + // Chez Bill, ils ont dit: "On va mettre les couleur dans l'ordre + // inverse, et pour faire chier, on va les mettre sur une échelle de + // 0 à 255 parce que le standard VGA c'est de 0 à 63 (logique!). Et + // puis comme c'est pas assez débile, on va aussi y rajouter un octet + // toujours à 0 pour forcer les gens à s'acheter des gros disques + // durs... Comme ça, ça fera passer la pillule lorsqu'on sortira + // Windows 95." ... + for (index=0; index<256; index++) + { + local_palette[index][0]=Main_palette[index].B; + local_palette[index][1]=Main_palette[index].G; + local_palette[index][2]=Main_palette[index].R; + local_palette[index][3]=0; + } + + if (Write_bytes(file,local_palette,1024)) + { + Init_write_buffer(); + + // ... Et Bill, il a dit: "OK les gars! Mais seulement si vous rangez + // les pixels dans l'ordre inverse, mais que sur les Y quand-même + // parce que faut pas pousser." + for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) + for (x_pos=0; x_pos>=current_nb_bits; + nb_bits_processed +=current_nb_bits; + nb_bits_to_process-=current_nb_bits; + GIF_remainder_bits -=current_nb_bits; + } + + return GIF_current_code; + } + + // -- Affiche un nouveau pixel -- + + void GIF_new_pixel(byte color) + { + Pixel_load_function(GIF_pos_X,GIF_pos_Y,color); + + GIF_pos_X++; + + if (GIF_pos_X>=Main_image_width) + { + GIF_pos_X=0; + + if (!GIF_interlaced) + GIF_pos_Y++; + else + { + switch (GIF_pass) + { + case 0 : GIF_pos_Y+=8; + break; + case 1 : GIF_pos_Y+=8; + break; + case 2 : GIF_pos_Y+=4; + break; + default: GIF_pos_Y+=2; + } + + if (GIF_pos_Y>=Main_image_height) + { + switch(++GIF_pass) + { + case 1 : GIF_pos_Y=4; + break; + case 2 : GIF_pos_Y=2; + break; + case 3 : GIF_pos_Y=1; + break; + case 4 : GIF_finished_interlaced_image=1; + } + } + } + } + } + + +void Load_GIF(void) +{ + char filename[MAX_PATH_CHARACTERS]; + char signature[6]; + + word * alphabet_stack; // Pile de décodage d'une chaîne + word * alphabet_prefix; // Table des préfixes des codes + word * alphabet_suffix; // Table des suffixes des codes + word alphabet_free; // Position libre dans l'alphabet + word alphabet_max; // Nombre d'entrées possibles dans l'alphabet + word alphabet_stack_pos; // Position dans la pile de décodage d'un chaîne + + T_GIF_LSDB LSDB; + T_GIF_IDB IDB; + + word nb_colors; // Nombre de couleurs dans l'image + word color_index; // index de traitement d'une couleur + byte size_to_read; // Nombre de données à lire (divers) + byte block_indentifier; // Code indicateur du type de bloc en cours + word initial_nb_bits; // Nb de bits au début du traitement LZW + word special_case=0; // Mémoire pour le cas spécial + word old_code=0; // Code précédent + word byte_read; // Sauvegarde du code en cours de lecture + word value_clr; // Valeur <=> Clear tables + word value_eof; // Valeur <=> End d'image + long file_size; + int number_LID; // Nombre d'images trouvées dans le fichier + + /////////////////////////////////////////////////// FIN DES DECLARATIONS // + + + GIF_pos_X=0; + GIF_pos_Y=0; + GIF_last_byte=0; + GIF_remainder_bits=0; + GIF_remainder_byte=0; + number_LID=0; + + Get_full_filename(filename,0); + + if ((GIF_file=fopen(filename, "rb"))) + { + file_size=File_length_file(GIF_file); + if ( (Read_bytes(GIF_file,signature,6)) && + ( (memcmp(signature,"GIF87a",6)==0) || + (memcmp(signature,"GIF89a",6)==0) ) ) + { + + // Allocation de mémoire pour les tables & piles de traitement: + alphabet_stack =(word *)malloc(4096*sizeof(word)); + alphabet_prefix=(word *)malloc(4096*sizeof(word)); + alphabet_suffix=(word *)malloc(4096*sizeof(word)); + + if (Read_word_le(GIF_file,&(LSDB.Width)) + && Read_word_le(GIF_file,&(LSDB.Height)) + && Read_byte(GIF_file,&(LSDB.Resol)) + && Read_byte(GIF_file,&(LSDB.Backcol)) + && Read_byte(GIF_file,&(LSDB.Aspect)) + ) + { + // Lecture du Logical Screen Descriptor Block réussie: + + Original_screen_X=LSDB.Width; + Original_screen_Y=LSDB.Height; + + // Palette globale dispo = (LSDB.Resol and $80) + // Profondeur de couleur =((LSDB.Resol and $70) shr 4)+1 + // Nombre de bits/pixel = (LSDB.Resol and $07)+1 + // Ordre de Classement = (LSDB.Aspect and $80) + + alphabet_stack_pos=0; + GIF_last_byte =0; + GIF_remainder_bits =0; + GIF_remainder_byte =0; + + nb_colors=(1 << ((LSDB.Resol & 0x07)+1)); + initial_nb_bits=(LSDB.Resol & 0x07)+2; + + if (LSDB.Resol & 0x80) + { + // Palette globale dispo: + + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + + // On peut maintenant charger la nouvelle palette: + if (!(LSDB.Aspect & 0x80)) + // Palette dans l'ordre: + for(color_index=0;color_indexnb_char_to_keep) + fseek(GIF_file,size_to_read-nb_char_to_keep,SEEK_CUR); + } + break; + case 0xF9: // Graphics Control Extension + // Prévu pour la transparence + + default: + // On saute le bloc: + fseek(GIF_file,size_to_read,SEEK_CUR); + break; + } + // Lecture de la taille du bloc suivant: + Read_byte(GIF_file,&size_to_read); + } + } + break; + case 0x2C: // Local Image Descriptor + { + // Si on a deja lu une image, c'est une GIF animée ou bizarroide, on sort. + if (number_LID!=0) + { + File_error=2; + break; + } + number_LID++; + + // lecture de 10 derniers octets + if ( Read_word_le(GIF_file,&(IDB.Pos_X)) + && Read_word_le(GIF_file,&(IDB.Pos_Y)) + && Read_word_le(GIF_file,&(IDB.Image_width)) + && Read_word_le(GIF_file,&(IDB.Image_height)) + && Read_byte(GIF_file,&(IDB.Indicator)) + && Read_byte(GIF_file,&(IDB.Nb_bits_pixel)) + && IDB.Image_width && IDB.Image_height) + { + Main_image_width=IDB.Image_width; + Main_image_height=IDB.Image_height; + + Init_preview(IDB.Image_width,IDB.Image_height,file_size,FORMAT_GIF,PIXEL_SIMPLE); + + // Palette locale dispo = (IDB.Indicator and $80) + // Image entrelacée = (IDB.Indicator and $40) + // Ordre de classement = (IDB.Indicator and $20) + // Nombre de bits/pixel = (IDB.Indicator and $07)+1 (si palette locale dispo) + + if (IDB.Indicator & 0x80) + { + // Palette locale dispo + + nb_colors=(1 << ((IDB.Indicator & 0x07)+1)); + initial_nb_bits=(IDB.Indicator & 0x07)+2; + + if (!(IDB.Indicator & 0x40)) + // Palette dans l'ordre: + for(color_index=0;color_indexvalue_clr) + { + alphabet_stack[alphabet_stack_pos++]=alphabet_suffix[GIF_current_code]; + GIF_current_code=alphabet_prefix[GIF_current_code]; + } + + special_case=alphabet_stack[alphabet_stack_pos++]=GIF_current_code; + + do + GIF_new_pixel(alphabet_stack[--alphabet_stack_pos]); + while (alphabet_stack_pos!=0); + + alphabet_prefix[alphabet_free ]=old_code; + alphabet_suffix[alphabet_free++]=GIF_current_code; + old_code=byte_read; + + if (alphabet_free>alphabet_max) + { + if (GIF_nb_bits<12) + alphabet_max =((1 << (++GIF_nb_bits))-1); + } + } + else // Code Clear rencontré + { + GIF_nb_bits =initial_nb_bits; + alphabet_max =((1 << GIF_nb_bits)-1); + alphabet_free =nb_colors+2; + special_case =GIF_get_next_code(); + old_code =GIF_current_code; + GIF_new_pixel(GIF_current_code); + } + } + else + File_error=2; + } // Code End-Of-Information ou erreur de fichier rencontré + + /*Close_lecture();*/ + + if (File_error>=0) + if ( /* (GIF_pos_X!=0) || */ + ( ( (!GIF_interlaced) && (GIF_pos_Y!=Main_image_height) ) || + ( (GIF_interlaced) && (!GIF_finished_interlaced_image) ) + ) ) + File_error=2; + } // Le fichier contenait un IDB + else + File_error=2; + } + default: + break; + } + // Lecture du code de fonction suivant: + Read_byte(GIF_file,&block_indentifier); + } + } // Le fichier contenait un LSDB + else + File_error=1; + + // Libération de la mémoire utilisée par les tables & piles de traitement: + free(alphabet_suffix); + free(alphabet_prefix); + free(alphabet_stack); + } // Le fichier contenait au moins la signature GIF87a ou GIF89a + else + File_error=1; + + fclose(GIF_file); + + } // Le fichier était ouvrable + else + File_error=1; +} + + +// -- Sauver un fichier au format GIF --------------------------------------- + + int GIF_stop; // "On peut arrêter la sauvegarde du fichier" + byte GIF_buffer[256]; // buffer d'écriture de bloc de données compilées + + // -- Vider le buffer GIF dans le buffer KM -- + + void GIF_empty_buffer(void) + { + word index; + + if (GIF_remainder_byte) + { + GIF_buffer[0]=GIF_remainder_byte; + + for (index=0;index<=GIF_remainder_byte;index++) + Write_one_byte(GIF_file,GIF_buffer[index]); + + GIF_remainder_byte=0; + } + } + + // -- Ecrit un code à GIF_nb_bits -- + + void GIF_set_code(word Code) + { + word nb_bits_to_process=GIF_nb_bits; + word nb_bits_processed =0; + word current_nb_bits; + + while (nb_bits_to_process) + { + current_nb_bits=(nb_bits_to_process<=(8-GIF_remainder_bits))?nb_bits_to_process:(8-GIF_remainder_bits); + + GIF_last_byte|=(Code & ((1<>=current_nb_bits; + GIF_remainder_bits +=current_nb_bits; + nb_bits_processed +=current_nb_bits; + nb_bits_to_process-=current_nb_bits; + + if (GIF_remainder_bits==8) // Il ne reste plus de bits à coder sur l'octet courant + { + // Ecrire l'octet à balancer: + GIF_buffer[++GIF_remainder_byte]=GIF_last_byte; + + // Si on a atteint la fin du bloc de Raster Data + if (GIF_remainder_byte==255) + // On doit vider le buffer qui est maintenant plein + GIF_empty_buffer(); + + GIF_last_byte=0; + GIF_remainder_bits=0; + } + } + } + + + // -- Lire le pixel suivant -- + + byte GIF_next_pixel(void) + { + byte temp; + + temp=Read_pixel_function(GIF_pos_X,GIF_pos_Y); + + if (++GIF_pos_X>=Main_image_width) + { + GIF_pos_X=0; + if (++GIF_pos_Y>=Main_image_height) + GIF_stop=1; + } + + return temp; + } + + + +void Save_GIF(void) +{ + char filename[MAX_PATH_CHARACTERS]; + + word * alphabet_prefix; // Table des préfixes des codes + word * alphabet_suffix; // Table des suffixes des codes + word * alphabet_daughter; // Table des chaînes filles (plus longues) + word * alphabet_sister; // Table des chaînes soeurs (même longueur) + word alphabet_free; // Position libre dans l'alphabet + word alphabet_max; // Nombre d'entrées possibles dans l'alphabet + word start; // Code précédent (sert au linkage des chaînes) + int descend; // Booléen "On vient de descendre" + + T_GIF_LSDB LSDB; + T_GIF_IDB IDB; + + + byte block_indentifier; // Code indicateur du type de bloc en cours + word current_string; // Code de la chaîne en cours de traitement + byte current_char; // Caractère à coder + word index; // index de recherche de chaîne + + + /////////////////////////////////////////////////// FIN DES DECLARATIONS // + + + GIF_pos_X=0; + GIF_pos_Y=0; + GIF_last_byte=0; + GIF_remainder_bits=0; + GIF_remainder_byte=0; + + Get_full_filename(filename,0); + + if ((GIF_file=fopen(filename,"wb"))) + { + // On écrit la signature du fichier + if (Write_bytes(GIF_file,"GIF89a",6)) + { + // La signature du fichier a été correctement écrite. + + // Allocation de mémoire pour les tables + alphabet_prefix=(word *)malloc(4096*sizeof(word)); + alphabet_suffix=(word *)malloc(4096*sizeof(word)); + alphabet_daughter =(word *)malloc(4096*sizeof(word)); + alphabet_sister =(word *)malloc(4096*sizeof(word)); + + // On initialise le LSDB du fichier + if (Config.Screen_size_in_GIF) + { + LSDB.Width=Screen_width; + LSDB.Height=Screen_height; + } + else + { + LSDB.Width=Main_image_width; + LSDB.Height=Main_image_height; + } + LSDB.Resol =0x97; // Image en 256 couleurs, avec une palette + LSDB.Backcol=0; + LSDB.Aspect =0; // Palette normale + + // On sauve le LSDB dans le fichier + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + LSDB.Width = SDL_Swap16(LSDB.Width); + LSDB.Height = SDL_Swap16(LSDB.Height); +#endif + + if (Write_bytes(GIF_file,&LSDB,sizeof(T_GIF_LSDB))) + { + // Le LSDB a été correctement écrit. + + // On sauve la palette + if (Write_bytes(GIF_file,Main_palette,768)) + { + // La palette a été correctement écrite. + + // Le jour où on se servira des blocks d'extensions pour placer + // des commentaires, on le fera ici. + + // Ecriture de la transparence + //Write_bytes(GIF_file,"\x21\xF9\x04\x01\x00\x00\xNN\x00",8); + + // Ecriture du commentaire + if (Main_comment[0]) + { + Write_bytes(GIF_file,"\x21\xFE",2); + Write_byte(GIF_file,strlen(Main_comment)); + Write_bytes(GIF_file,Main_comment,strlen(Main_comment)+1); + } + + + + // On va écrire un block indicateur d'IDB et l'IDB du fichier + + block_indentifier=0x2C; + IDB.Pos_X=0; + IDB.Pos_Y=0; + IDB.Image_width=Main_image_width; + IDB.Image_height=Main_image_height; + IDB.Indicator=0x07; // Image non entrelacée, pas de palette locale. + IDB.Nb_bits_pixel=8; // Image 256 couleurs; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + IDB.Image_width = SDL_Swap16(IDB.Image_width); + IDB.Image_height = SDL_Swap16(IDB.Image_height); +#endif + + if ( Write_bytes(GIF_file,&block_indentifier,1) && + Write_bytes(GIF_file,&IDB,sizeof(T_GIF_IDB)) ) + { + // Le block indicateur d'IDB et l'IDB ont étés correctements + // écrits. + + Init_write_buffer(); + + index=4096; + File_error=0; + GIF_stop=0; + + // Réintialisation de la table: + alphabet_free=258; + GIF_nb_bits =9; + alphabet_max =511; + GIF_set_code(256); + for (start=0;start<4096;start++) + { + alphabet_daughter[start]=4096; + alphabet_sister[start]=4096; + } + + ////////////////////////////////////////////// COMPRESSION LZW // + + start=current_string=GIF_next_pixel(); + descend=1; + + do + { + current_char=GIF_next_pixel(); + + // On regarde si dans la table on aurait pas une chaîne + // équivalente à current_string+Caractere + + while ( (index0xFFF) + { + // Réintialisation de la table: + GIF_set_code(256); + alphabet_free=258; + GIF_nb_bits =9; + alphabet_max =511; + for (start=0;start<4096;start++) + { + alphabet_daughter[start]=4096; + alphabet_sister[start]=4096; + } + } + else if (alphabet_free>alphabet_max+1) + { + // On augmente le nb de bits + + GIF_nb_bits++; + alphabet_max=(1< 16c , 1 => 256c , ... + word Bytes_per_plane_line;// Doit toujours être pair + word Palette_info; // 1 => color , 2 => Gris (ignoré à partir de la version 4) + word Screen_X; // |_ Dimensions de + word Screen_Y; // | l'écran d'origine + byte Filler[54]; // Ca... J'adore! + } T_PCX_Header; +#pragma pack() + +T_PCX_Header PCX_header; + +// -- Tester si un fichier est au format PCX -------------------------------- + +void Test_PCX(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + + File_error=0; + Get_full_filename(filename,0); + + if ((file=fopen(filename, "rb"))) + { + if (Read_byte(file,&(PCX_header.Manufacturer)) && + Read_byte(file,&(PCX_header.Version)) && + Read_byte(file,&(PCX_header.Compression)) && + Read_byte(file,&(PCX_header.Depth)) && + Read_word_le(file,&(PCX_header.X_min)) && + Read_word_le(file,&(PCX_header.Y_min)) && + Read_word_le(file,&(PCX_header.X_max)) && + Read_word_le(file,&(PCX_header.Y_max)) && + Read_word_le(file,&(PCX_header.X_dpi)) && + Read_word_le(file,&(PCX_header.Y_dpi)) && + Read_bytes(file,&(PCX_header.Palette_16c),48) && + Read_byte(file,&(PCX_header.Reserved)) && + Read_byte(file,&(PCX_header.Plane)) && + Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) && + Read_word_le(file,&(PCX_header.Palette_info)) && + Read_word_le(file,&(PCX_header.Screen_X)) && + Read_word_le(file,&(PCX_header.Screen_Y)) && + Read_bytes(file,&(PCX_header.Filler),54) ) + { + + // Vu que ce header a une signature de merde et peu significative, il + // va falloir que je teste différentes petites valeurs dont je connais + // l'intervalle. Grrr! + if ( (PCX_header.Manufacturer!=10) + || (PCX_header.Compression>1) + || ( (PCX_header.Depth!=1) && (PCX_header.Depth!=2) && (PCX_header.Depth!=4) && (PCX_header.Depth!=8) ) + || ( (PCX_header.Plane!=1) && (PCX_header.Plane!=2) && (PCX_header.Plane!=4) && (PCX_header.Plane!=8) && (PCX_header.Plane!=3) ) + || (PCX_header.X_max>((reduction_minus_one-(x_pos%reduction))*depth)) & byte_mask; + Pixel_load_function(x_pos,y_pos,color); + } + } + +void Load_PCX(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + + short line_size; + short real_line_size; // width de l'image corrigée + short width_read; + short x_pos; + short y_pos; + byte byte1; + byte byte2; + byte index; + dword nb_colors; + long file_size; + byte palette_CGA[9]={ 84,252,252, 252, 84,252, 252,252,252}; + + long position; + long image_size; + byte * buffer; + + Get_full_filename(filename,0); + + File_error=0; + + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + /* + if (Read_bytes(file,&PCX_header,sizeof(T_PCX_Header))) + {*/ + + if (Read_byte(file,&(PCX_header.Manufacturer)) && + Read_byte(file,&(PCX_header.Version)) && + Read_byte(file,&(PCX_header.Compression)) && + Read_byte(file,&(PCX_header.Depth)) && + Read_word_le(file,&(PCX_header.X_min)) && + Read_word_le(file,&(PCX_header.Y_min)) && + Read_word_le(file,&(PCX_header.X_max)) && + Read_word_le(file,&(PCX_header.Y_max)) && + Read_word_le(file,&(PCX_header.X_dpi)) && + Read_word_le(file,&(PCX_header.Y_dpi)) && + Read_bytes(file,&(PCX_header.Palette_16c),48) && + Read_byte(file,&(PCX_header.Reserved)) && + Read_byte(file,&(PCX_header.Plane)) && + Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) && + Read_word_le(file,&(PCX_header.Palette_info)) && + Read_word_le(file,&(PCX_header.Screen_X)) && + Read_word_le(file,&(PCX_header.Screen_Y)) && + Read_bytes(file,&(PCX_header.Filler),54) ) + { + + Main_image_width=PCX_header.X_max-PCX_header.X_min+1; + Main_image_height=PCX_header.Y_max-PCX_header.Y_min+1; + + Original_screen_X=PCX_header.Screen_X; + Original_screen_Y=PCX_header.Screen_Y; + + if (PCX_header.Plane!=3) + { + Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_PCX,PIXEL_SIMPLE); + if (File_error==0) + { + // On prépare la palette à accueillir les valeurs du fichier PCX + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + nb_colors=(dword)(1<4) + memcpy(Main_palette,PCX_header.Palette_16c,48); + else + { + Main_palette[1].R=0; + Main_palette[1].G=0; + Main_palette[1].B=0; + byte1=PCX_header.Palette_16c[3]>>5; + if (nb_colors==4) + { // Pal. CGA "alakon" (du Turc Allahkoum qui signifie "à la con" :)) + memcpy(Main_palette+1,palette_CGA,9); + if (!(byte1&2)) + { + Main_palette[1].B=84; + Main_palette[2].B=84; + Main_palette[3].B=84; + } + } // Palette monochrome (on va dire que c'est du N&B) + else + { + Main_palette[1].R=252; + Main_palette[1].G=252; + Main_palette[1].B=252; + } + } + + // On se positionne à la fin du fichier - 769 octets pour voir s'il y + // a une palette. + if ( (PCX_header.Depth==8) && (PCX_header.Version>=5) && (file_size>(256*3)) ) + { + fseek(file,file_size-((256*3)+1),SEEK_SET); + // On regarde s'il y a une palette après les données de l'image + if (Read_byte(file,&byte1)) + if (byte1==12) // Lire la palette si c'est une image en 256 couleurs + { + int index; + // On lit la palette 256c que ces crétins ont foutue à la fin du fichier + for(index=0;index<256;index++) + if ( ! Read_byte(file,&Main_palette[index].R) + || ! Read_byte(file,&Main_palette[index].G) + || ! Read_byte(file,&Main_palette[index].B) ) + { + File_error=2; + DEBUG("ERROR READING PCX PALETTE !",index); + break; + } + } + } + Set_palette(Main_palette); + Remap_fileselector(); + + // Maintenant qu'on a lu la palette que ces crétins sont allés foutre + // à la fin, on retourne juste après le header pour lire l'image. + fseek(file,128,SEEK_SET); + if (!File_error) + { + line_size=PCX_header.Bytes_per_plane_line*PCX_header.Plane; + real_line_size=(short)PCX_header.Bytes_per_plane_line<<3; + // On se sert de données LBM car le dessin de ligne en moins de 256 + // couleurs se fait comme avec la structure ILBM. + Image_HAM=0; + HBPm1=PCX_header.Plane-1; + LBM_buffer=(byte *)malloc(line_size); + + // Chargement de l'image + if (PCX_header.Compression) // Image compressée + { + /*Init_lecture();*/ + + image_size=(long)PCX_header.Bytes_per_plane_line*Main_image_height; + + if (PCX_header.Depth==8) // 256 couleurs (1 plan) + { + for (position=0; ((position=line_size) + { + for (x_pos=0; x_pos=line_size) + { + for (x_pos=0; x_pos1) || (last_pixel>=0xC0) ) + Write_one_byte(file,counter|0xC0); + Write_one_byte(file,last_pixel); + + } + } + + // Ecriture de l'octet (12) indiquant que la palette arrive + if (!File_error) + Write_one_byte(file,12); + + End_write(file); + + // Ecriture de la palette + if (!File_error) + { + if (! Write_bytes(file,Main_palette,sizeof(T_Palette))) + File_error=1; + } + } + else + File_error=1; + + fclose(file); + + if (File_error) + remove(filename); + + } + else + File_error=1; +} + + +//////////////////////////////////// SCx //////////////////////////////////// +#pragma pack(1) +typedef struct +{ + byte Filler1[4]; + word Width; + word Height; + byte Filler2; + byte Planes; +} T_SCx_Header; +#pragma pack() + +// -- Tester si un fichier est au format SCx -------------------------------- +void Test_SCx(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + //byte Signature[3]; + T_SCx_Header SCx_header; + + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Lecture et vérification de la signature + if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header)))) + { + if ( (!memcmp(SCx_header.Filler1,"RIX",3)) + && SCx_header.Width && SCx_header.Height) + File_error=0; + } + // Fermeture du fichier + fclose(file); + } +} + + +// -- Lire un fichier au format SCx ----------------------------------------- +void Load_SCx(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + word x_pos,y_pos; + long size,real_size; + long file_size; + T_SCx_Header SCx_header; + T_Palette SCx_Palette; + + Get_full_filename(filename,0); + + File_error=0; + + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + + if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header)))) + { + Init_preview(SCx_header.Width,SCx_header.Height,file_size,FORMAT_SCx,PIXEL_SIMPLE); + if (File_error==0) + { + if (!SCx_header.Planes) + size=sizeof(T_Palette); + else + size=sizeof(T_Components)*(1<>3)*SCx_header.Planes; + real_size=(size/SCx_header.Planes)<<3; + LBM_buffer=(byte *)malloc(size); + HBPm1=SCx_header.Planes-1; + Image_HAM=0; + + for (y_pos=0;(y_poscolor_type; + bit_depth = info_ptr->bit_depth; + + // If it's any supported file + // (Note: As of writing this, this test covers every possible + // image format of libpng) + if (color_type == PNG_COLOR_TYPE_PALETTE + || color_type == PNG_COLOR_TYPE_GRAY + || color_type == PNG_COLOR_TYPE_GRAY_ALPHA + || color_type == PNG_COLOR_TYPE_RGB + || color_type == PNG_COLOR_TYPE_RGB_ALPHA + ) + { + int num_text; + png_text *text_ptr; + + int unit_type; + png_uint_32 res_x; + png_uint_32 res_y; + + // Comment (tEXt) + Main_comment[0]='\0'; // Clear the previous comment + if ((num_text=png_get_text(png_ptr, info_ptr, &text_ptr, NULL))) + { + while (num_text--) + { + if (!strcmp(text_ptr[num_text].key,"Title")) + { + int size; + size = Min(text_ptr[num_text].text_length, COMMENT_SIZE); + strncpy(Main_comment, text_ptr[num_text].text, size); + Main_comment[size]='\0'; + break; // Skip all others tEXt chunks + } + } + } + // Pixel Ratio (pHYs) + if (png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type)) + { + // Ignore unit, and use the X/Y ratio as a hint for + // WIDE or TALL pixels + if (res_x>0 && res_y>0) + { + if (res_y/res_x>1) + { + Ratio_of_loaded_image=PIXEL_WIDE; + } + else if (res_x/res_y>1) + { + Ratio_of_loaded_image=PIXEL_TALL; + } + } + } + if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) + Init_preview_24b(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG); + else + Init_preview(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG,Ratio_of_loaded_image); + + if (File_error==0) + { + int x,y; + png_colorp palette; + int num_palette; + + // 16-bit images + if (bit_depth == 16) + { + // Reduce to 8-bit + png_set_strip_16(png_ptr); + } + else if (bit_depth < 8) + { + // Inform libpng we want one byte per pixel, + // even though the file was less than 8bpp + png_set_packing(png_ptr); + } + + // Images with alpha channel + if (color_type & PNG_COLOR_MASK_ALPHA) + { + // Tell libpng to ignore it + png_set_strip_alpha(png_ptr); + } + + // Greyscale images : + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + // Map low bpp greyscales to full 8bit (0-255 range) + if (bit_depth < 8) + png_set_gray_1_2_4_to_8(png_ptr); + + // Create greyscale palette + for (x=0;x<256;x++) + { + Main_palette[x].R=x; + Main_palette[x].G=x; + Main_palette[x].B=x; + } + } + else if (color_type == PNG_COLOR_TYPE_PALETTE) // Palette images + { + + if (bit_depth < 8) + { + // Clear unused colors + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + } + // Load the palette + png_get_PLTE(png_ptr, info_ptr, &palette, + &num_palette); + for (x=0;xwidth; + Main_image_height=info_ptr->height; + + png_set_interlace_handling(png_ptr); + png_read_update_info(png_ptr, info_ptr); + + // Allocate row pointers + Row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * Main_image_height); + row_pointers_allocated = 0; + + /* read file */ + if (!setjmp(png_jmpbuf(png_ptr))) + { + if (color_type == PNG_COLOR_TYPE_GRAY + || color_type == PNG_COLOR_TYPE_GRAY_ALPHA + || color_type == PNG_COLOR_TYPE_PALETTE + ) + { + // 8bpp + + for (y=0; yrowbytes); + row_pointers_allocated = 1; + + png_read_image(png_ptr, Row_pointers); + + for (y=0; yrowbytes); + row_pointers_allocated = 1; + + png_read_image(png_ptr, Row_pointers); + + for (y=0; y #include #include -#ifndef __no_pnglib__ -#include -#endif #include #include @@ -132,26 +129,27 @@ void Load_SDL_Image(void); void Init_preview(short width,short height,long size,int format,enum PIXEL_RATIO ratio); +// ENUM Name TestFunc LoadFunc SaveFunc Backup Comment Ext Exts T_Format File_formats[NB_KNOWN_FORMATS] = { - {FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, "", "gif;png;bmp;pcx;pkm;lbm;iff;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"}, - {FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, "", "*"}, + {FORMAT_ALL_IMAGES,"(all)",NULL, NULL, NULL, 0, 0, "", "gif;png;bmp;pcx;pkm;lbm;iff;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"}, + {FORMAT_ALL_FILES,"(*.*)",NULL, NULL, NULL, 0, 0, "", "*"}, {FORMAT_GIF, " gif", Test_GIF, Load_GIF, Save_GIF, 1, 1, "gif", "gif"}, #ifndef __no_pnglib__ {FORMAT_PNG, " png", Test_PNG, Load_PNG, Save_PNG, 1, 1, "png", "png"}, #endif {FORMAT_BMP, " bmp", Test_BMP, Load_BMP, Save_BMP, 1, 0, "bmp", "bmp"}, {FORMAT_PCX, " pcx", Test_PCX, Load_PCX, Save_PCX, 1, 0, "pcx", "pcx"}, - {FORMAT_PKM, " pkm", Test_PKM, Load_PKM, Save_PKM, 1, 1, "pkm", "pkm"}, + {FORMAT_PKM, " pkm", Test_PKM, Load_PKM, Save_PKM, 0, 1, "pkm", "pkm"}, // Not a backup since it does not save the full palette {FORMAT_LBM, " lbm", Test_LBM, Load_LBM, Save_LBM, 1, 0, "lbm", "lbm;iff"}, {FORMAT_IMG, " img", Test_IMG, Load_IMG, Save_IMG, 1, 0, "img", "img"}, {FORMAT_SCx, " sc?", Test_SCx, Load_SCx, Save_SCx, 1, 0, "sc?", "sci;scq;scf;scn;sco"}, - {FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 1, 0, "pi1", "pi1"}, - {FORMAT_PC1, " pc1", Test_PC1, Load_PC1, Save_PC1, 1, 0, "pc1", "pc1"}, + {FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 0, 0, "pi1", "pi1"}, + {FORMAT_PC1, " pc1", Test_PC1, Load_PC1, Save_PC1, 0, 0, "pc1", "pc1"}, {FORMAT_CEL, " cel", Test_CEL, Load_CEL, Save_CEL, 1, 0, "cel", "cel"}, - {FORMAT_NEO, " neo", Test_NEO, Load_NEO, Save_NEO, 1, 0, "neo", "neo"}, + {FORMAT_NEO, " neo", Test_NEO, Load_NEO, Save_NEO, 0, 0, "neo", "neo"}, {FORMAT_KCF, " kcf", Test_KCF, Load_KCF, Save_KCF, 0, 0, "kcf", "kcf"}, {FORMAT_PAL, " pal", Test_PAL, Load_PAL, Save_PAL, 0, 0, "pal", "pal"}, - {FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 1, 1, "c64", "c64;koa"}, + {FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, "c64", "c64;koa"}, {FORMAT_MISC,"misc.", NULL, NULL, NULL, 1, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"}, }; @@ -182,8 +180,6 @@ short Preview_factor_Y; short Preview_pos_X; short Preview_pos_Y; -byte HBPm1; // header.BitPlanes-1 - // Chargement des pixels dans la preview void Pixel_load_in_preview(word x_pos,word y_pos,byte color) @@ -271,12 +267,7 @@ void Remap_fileselector(void) } } - - -// Données pour la gestion du chargement en 24b -#define FORMAT_24B 0x100 -typedef void (* Func_24b_display) (short,short,byte,byte,byte); -int Image_24b; +int Image_24b; T_Components * Buffer_image_24b; Func_24b_display Pixel_load_24b; @@ -784,6098 +775,6 @@ void Save_image(byte image) } -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// PAL //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -// -- Tester si un fichier est au format PAL -------------------------------- -void Test_PAL(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - long file_size; // Taille du fichier - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Lecture de la taille du fichier - file_size=File_length_file(file); - fclose(file); - // Le fichier ne peut être au format PAL que si sa taille vaut 768 octets - if (file_size==sizeof(T_Palette)) - File_error=0; - } -} - - -// -- Lire un fichier au format PAL ----------------------------------------- -void Load_PAL(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - //long file_size; // Taille du fichier - - - Get_full_filename(filename,0); - File_error=0; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - T_Palette palette_64; - // Init_preview(?); // Pas possible... pas d'image... - - // Lecture du fichier dans Main_palette - if (Read_bytes(file,palette_64,sizeof(T_Palette))) - { - Palette_64_to_256(palette_64); - memcpy(Main_palette,palette_64,sizeof(T_Palette)); - Set_palette(Main_palette); - Remap_fileselector(); - - // On dessine une preview de la palette (si chargement=preview) - Draw_palette_preview(); - } - else - File_error=2; - - // Fermeture du fichier - fclose(file); - } - else - // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur - File_error=1; -} - - -// -- Sauver un fichier au format PAL --------------------------------------- -void Save_PAL(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - //long file_size; // Taille du fichier - - Get_full_filename(filename,0); - - File_error=0; - - // Ouverture du fichier - if ((file=fopen(filename,"wb"))) - { - T_Palette palette_64; - memcpy(palette_64,Main_palette,sizeof(T_Palette)); - Palette_256_to_64(palette_64); - // Enregistrement de Main_palette dans le fichier - if (! Write_bytes(file,palette_64,sizeof(T_Palette))) - { - File_error=1; - fclose(file); - remove(filename); - } - else // Ecriture correcte => Fermeture normale du fichier - fclose(file); - } - else // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur - { - File_error=1; - fclose(file); - remove(filename); - // On se fout du résultat de l'opération car si ça - // renvoie 0 c'est que le fichier avait été partiel- - // -lement écrit, sinon pas du tout. Or dans tous les - // cas ça revient au même pour nous: Sauvegarde ratée! - } -} - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// IMG //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -#pragma pack(1) -typedef struct -{ - byte Filler1[6]; - word Width; - word Height; - byte Filler2[118]; - T_Palette Palette; -} T_IMG_Header; -#pragma pack() - -// -- Tester si un fichier est au format IMG -------------------------------- -void Test_IMG(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - T_IMG_Header IMG_header; - byte signature[6]={0x01,0x00,0x47,0x12,0x6D,0xB0}; - - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Lecture et vérification de la signature - if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header))) - { - if ( (!memcmp(IMG_header.Filler1,signature,6)) - && IMG_header.Width && IMG_header.Height) - File_error=0; - } - // Fermeture du fichier - fclose(file); - } -} - - -// -- Lire un fichier au format IMG ----------------------------------------- -void Load_IMG(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - byte * buffer; - FILE *file; - word x_pos,y_pos; - long width_read; - long file_size; - T_IMG_Header IMG_header; - - Get_full_filename(filename,0); - File_error=0; - - if ((file=fopen(filename, "rb"))) - { - file_size=File_length_file(file); - - if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header))) - { - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - IMG_header.Width = SDL_Swap16(IMG_header.Width); - IMG_header.Height = SDL_Swap16(IMG_header.Height); -#endif - - buffer=(byte *)malloc(IMG_header.Width); - - Init_preview(IMG_header.Width,IMG_header.Height,file_size,FORMAT_IMG,PIXEL_SIMPLE); - if (File_error==0) - { - memcpy(Main_palette,IMG_header.Palette,sizeof(T_Palette)); - Set_palette(Main_palette); - Remap_fileselector(); - - Main_image_width=IMG_header.Width; - Main_image_height=IMG_header.Height; - width_read=IMG_header.Width; - - for (y_pos=0;(y_posCOMMENT_SIZE) - { - color=temp_byte; // On se sert de color comme - temp_byte=COMMENT_SIZE; // variable temporaire - color-=COMMENT_SIZE; - } - else - color=0; - - if (Read_bytes(file,Main_comment,temp_byte)) - { - index+=temp_byte; - Main_comment[temp_byte]='\0'; - if (color) - if (fseek(file,color,SEEK_CUR)) - File_error=2; - } - else - File_error=2; - } - else - File_error=2; - break; - - case 1 : // Dimensions de l'écran d'origine - if (Read_byte(file,&temp_byte)) - { - if (temp_byte==4) - { - index+=4; - if ( ! Read_word_le(file,(word *) &Original_screen_X) - || !Read_word_le(file,(word *) &Original_screen_Y) ) - File_error=2; - } - else - File_error=2; - } - else - File_error=2; - break; - - case 2 : // color de transparence - if (Read_byte(file,&temp_byte)) - { - if (temp_byte==1) - { - index++; - if (! Read_byte(file,&Back_color)) - File_error=2; - } - else - File_error=2; - } - else - File_error=2; - break; - - default: - if (Read_byte(file,&temp_byte)) - { - index+=temp_byte; - if (fseek(file,temp_byte,SEEK_CUR)) - File_error=2; - } - else - File_error=2; - } - } - else - File_error=2; - } - if ( (!File_error) && (index!=header.Jump) ) - File_error=2; - } - - /*Init_lecture();*/ - - if (!File_error) - { - Init_preview(header.Width,header.Height,file_size,FORMAT_PKM,PIXEL_SIMPLE); - if (File_error==0) - { - - Main_image_width=header.Width; - Main_image_height=header.Height; - image_size=(dword)(Main_image_width*Main_image_height); - // Palette lue en 64 - memcpy(Main_palette,header.Palette,sizeof(T_Palette)); - Palette_64_to_256(Main_palette); - Set_palette(Main_palette); - Remap_fileselector(); - - Compteur_de_donnees_packees=0; - Compteur_de_pixels=0; - Taille_pack=(file_size)-sizeof(T_PKM_Header)-header.Jump; - - // Boucle de décompression: - while ( (Compteur_de_pixels>8); - Write_one_byte(file,Screen_height&0xFF); - Write_one_byte(file,Screen_height>>8); - // Ecriture de la back-color - Write_one_byte(file,2); - Write_one_byte(file,1); - Write_one_byte(file,Back_color); - - // Routine de compression PKM de l'image - image_size=(dword)(Main_image_width*Main_image_height); - Compteur_de_pixels=0; - pixel_value=Read_pixel_function(0,0); - - while ( (Compteur_de_pixels=image_size) break; - pixel_value=Read_pixel_function(Compteur_de_pixels % Main_image_width,Compteur_de_pixels / Main_image_width); - } - - if ( (last_color!=header.recog1) && (last_color!=header.recog2) ) - { - if (repetitions==1) - Write_one_byte(file,last_color); - else - if (repetitions==2) - { - Write_one_byte(file,last_color); - Write_one_byte(file,last_color); - } - else - if ( (repetitions>2) && (repetitions<256) ) - { // RECON1/couleur/nombre - Write_one_byte(file,header.recog1); - Write_one_byte(file,last_color); - Write_one_byte(file,repetitions&0xFF); - } - else - if (repetitions>=256) - { // RECON2/couleur/hi(nombre)/lo(nombre) - Write_one_byte(file,header.recog2); - Write_one_byte(file,last_color); - Write_one_byte(file,repetitions>>8); - Write_one_byte(file,repetitions&0xFF); - } - } - else - { - if (repetitions<256) - { - Write_one_byte(file,header.recog1); - Write_one_byte(file,last_color); - Write_one_byte(file,repetitions&0xFF); - } - else - { - Write_one_byte(file,header.recog2); - Write_one_byte(file,last_color); - Write_one_byte(file,repetitions>>8); - Write_one_byte(file,repetitions&0xFF); - } - } - } - - End_write(file); - } - else - File_error=1; - fclose(file); - } - else - { - File_error=1; - fclose(file); - } - // S'il y a eu une erreur de sauvegarde, on ne va tout de même pas laisser - // ce fichier pourri traîner... Ca fait pas propre. - if (File_error) - remove(filename); -} - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// LBM //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -#pragma pack(1) -typedef struct -{ - word Width; - word Height; - word X_org; // Inutile - word Y_org; // Inutile - byte BitPlanes; - byte Mask; - byte Compression; - byte Pad1; // Inutile - word Transp_col; - byte X_aspect; // Inutile - byte Y_aspect; // Inutile - word X_screen; - word Y_screen; -} T_LBM_Header; -#pragma pack() - -byte * LBM_buffer; -FILE *LBM_file; - -// -- Tester si un fichier est au format LBM -------------------------------- - -void Test_LBM(void) -{ - char filename[MAX_PATH_CHARACTERS]; - char format[4]; - char section[4]; - dword dummy; - - Get_full_filename(filename,0); - - File_error=0; - - if ((LBM_file=fopen(filename, "rb"))) - { - if (! Read_bytes(LBM_file,section,4)) - File_error=1; - else - if (memcmp(section,"FORM",4)) - File_error=1; - else - { - Read_dword_be(LBM_file, &dummy); - // On aurait pu vérifier que ce long est égal à la taille - // du fichier - 8, mais ça aurait interdit de charger des - // fichiers tronqués (et déjà que c'est chiant de perdre - // une partie du fichier il faut quand même pouvoir en - // garder un peu... Sinon, moi je pleure :'( !!! ) - if (! Read_bytes(LBM_file,format,4)) - File_error=1; - else - if ( (memcmp(format,"ILBM",4)) && (memcmp(format,"PBM ",4)) ) - File_error=1; - } - fclose(LBM_file); - } - else - File_error=1; -} - - -// -- Lire un fichier au format LBM ----------------------------------------- - - byte Image_HAM; - - // ---------------- Adapter la palette pour les images HAM ---------------- - void Adapt_palette_HAM(void) - { - short i,j,temp; - byte color; - - if (Image_HAM==6) - { - for (i=1; i<=14; i++) - { - // On recopie a palette de base - memcpy(Main_palette+(i<<4),Main_palette,48); - // On modifie les teintes de cette palette - for (j=0; j<16; j++) - { - color=(i<<4)+j; - if (i<=7) - { - if (i&1) - { - temp=Main_palette[j].R+16; - Main_palette[color].R=(temp<63)?temp:63; - } - if (i&2) - { - temp=Main_palette[j].G+16; - Main_palette[color].G=(temp<63)?temp:63; - } - if (i&4) - { - temp=Main_palette[j].B+16; - Main_palette[color].B=(temp<63)?temp:63; - } - } - else - { - if ((i-7)&1) - { - temp=Main_palette[j].R-16; - Main_palette[color].R=(temp>=0)?temp:0; - } - if ((i-7)&2) - { - temp=Main_palette[j].G-16; - Main_palette[color].G=(temp>=0)?temp:0; - } - if ((i-7)&4) - { - temp=Main_palette[j].B-16; - Main_palette[color].B=(temp>=0)?temp:0; - } - } - } - } - // Ici, il reste les 16 dernières couleurs à modifier - for (i=240,j=0; j<16; i++,j++) - { - temp=Main_palette[j].R+8; - Main_palette[i].R=(temp<63)?temp:63; - temp=Main_palette[j].G+8; - Main_palette[i].G=(temp<63)?temp:63; - temp=Main_palette[j].B+8; - Main_palette[i].B=(temp<63)?temp:63; - } - } - else if (Image_HAM==8) - { - for (i=1; i<=3; i++) - { - // On recopie la palette de base - memcpy(Main_palette+(i<<6),Main_palette,192); - // On modifie les teintes de cette palette - for (j=0; j<64; j++) - { - color=(i<<6)+j; - switch (i) - { - case 1 : - temp=Main_palette[j].R+16; - Main_palette[color].R=(temp<63)?temp:63; - break; - case 2 : - temp=Main_palette[j].G+16; - Main_palette[color].G=(temp<63)?temp:63; - break; - default: - temp=Main_palette[j].B+16; - Main_palette[color].B=(temp<63)?temp:63; - } - } - } - } - else // Image 64 couleurs sauvée en 32. - { - for (i=0; i<32; i++) - { - j=i+32; - Main_palette[j].R=Main_palette[i].R>>1; - Main_palette[j].G=Main_palette[i].G>>1; - Main_palette[j].B=Main_palette[i].B>>1; - } - } - } - - // ------------------------- Attendre une section ------------------------- - byte Wait_for(byte * expected_section) - { - // Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur) - dword Taille_section; - byte section_read[4]; - - if (! Read_bytes(LBM_file,section_read,4)) - return 0; - while (memcmp(section_read,expected_section,4)) // Sect. pas encore trouvée - { - if (!Read_dword_be(LBM_file,&Taille_section)) - return 0; - if (Taille_section&1) - Taille_section++; - if (fseek(LBM_file,Taille_section,SEEK_CUR)) - return 0; - if (! Read_bytes(LBM_file,section_read,4)) - return 0; - } - return 1; - } - -// Les images ILBM sont stockés en bitplanes donc on doit trifouiller les bits pour -// en faire du chunky - -byte Color_ILBM_line(word x_pos, word real_line_size, byte HBPm1) -{ - // Renvoie la couleur du pixel (ILBM) en x_pos. - // CL sera le rang auquel on extrait les bits de la couleur - byte cl = 7 - (x_pos & 7); - int ax,bh,dx; - byte bl=0; - - for(dx=HBPm1;dx>=0;dx--) - { - //CIL_Loop - ax = (real_line_size * dx + x_pos) >> 3; - bh = (LBM_buffer[ax] >> cl) & 1; - - bl = (bl << 1) + bh; - } - - return bl; -} - - // ----------------------- Afficher une ligne ILBM ------------------------ - void Draw_ILBM_line(short y_pos, short real_line_size) - { - byte color; - byte red,green,blue; - byte temp; - short x_pos; - - if (Image_HAM<=1) // ILBM - { - for (x_pos=0; x_pos>2; - color=Best_color(red,green,blue); - break; - case 0x02: // red - red=temp>>2; - color=Best_color(red,green,blue); - break; - case 0x03: // green - green=temp>>2; - color=Best_color(red,green,blue); - break; - default: // Nouvelle couleur - color=temp; - red=Main_palette[color].R; - green =Main_palette[color].G; - blue =Main_palette[color].B; - } - Pixel_load_function(x_pos,y_pos,color); - } - } - } - - -void Load_LBM(void) -{ - char filename[MAX_PATH_CHARACTERS]; - T_LBM_Header header; - char format[4]; - char section[4]; - byte temp_byte; - short b256; - dword nb_colors; - dword image_size; - short x_pos; - short y_pos; - short counter; - short line_size; // Taille d'une ligne en octets - short real_line_size; // Taille d'une ligne en pixels - byte color; - long file_size; - dword dummy; - - Get_full_filename(filename,0); - - File_error=0; - - if ((LBM_file=fopen(filename, "rb"))) - { - file_size=File_length_file(LBM_file); - - // On avance dans le fichier (pas besoin de tester ce qui l'a déjà été) - Read_bytes(LBM_file,section,4); - Read_dword_be(LBM_file,&dummy); - Read_bytes(LBM_file,format,4); - if (!Wait_for((byte *)"BMHD")) - File_error=1; - Read_dword_be(LBM_file,&dummy); - - // Maintenant on lit le header pour pouvoir commencer le chargement de l'image - if ( (Read_word_be(LBM_file,&header.Width)) - && (Read_word_be(LBM_file,&header.Height)) - && (Read_word_be(LBM_file,&header.X_org)) - && (Read_word_be(LBM_file,&header.Y_org)) - && (Read_byte(LBM_file,&header.BitPlanes)) - && (Read_byte(LBM_file,&header.Mask)) - && (Read_byte(LBM_file,&header.Compression)) - && (Read_byte(LBM_file,&header.Pad1)) - && (Read_word_be(LBM_file,&header.Transp_col)) - && (Read_byte(LBM_file,&header.X_aspect)) - && (Read_byte(LBM_file,&header.Y_aspect)) - && (Read_word_be(LBM_file,&header.X_screen)) - && (Read_word_be(LBM_file,&header.Y_screen)) - && header.Width && header.Height) - { - if ( (header.BitPlanes) && (Wait_for((byte *)"CMAP")) ) - { - Read_dword_be(LBM_file,&nb_colors); - nb_colors/=3; - - if (((dword)1< il faut copier les 32 coul. - } // sur les 32 suivantes et assombrir ces dernières. - else - { - if ((header.BitPlanes==6) || (header.BitPlanes==8)) - Image_HAM=header.BitPlanes; - else - /* File_error=1;*/ /* C'est censé être incorrect mais j'ai */ - Image_HAM=0; /* trouvé un fichier comme ça, alors... */ - } - } - else - Image_HAM=0; - - if ( (!File_error) && (nb_colors>=2) && (nb_colors<=256) ) - { - HBPm1=header.BitPlanes-1; - if (header.Mask==1) - header.BitPlanes++; - - // Deluxe paint le fait... alors on le fait... - Back_color=header.Transp_col; - - // On commence par passer la palette en 256 comme ça, si la nouvelle - // palette a moins de 256 coul, la précédente ne souffrira pas d'un - // assombrissement préjudiciable. - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - else - Palette_64_to_256(Main_palette); - // On peut maintenant charger la nouvelle palette - if (Read_bytes(LBM_file,Main_palette,3*nb_colors)) - { - Palette_256_to_64(Main_palette); - if (Image_HAM) - Adapt_palette_HAM(); - Palette_64_to_256(Main_palette); - Set_palette(Main_palette); - Remap_fileselector(); - - // On lit l'octet de padding du CMAP si la taille est impaire - if (nb_colors&1) - if (Read_byte(LBM_file,&temp_byte)) - File_error=2; - - if ( (Wait_for((byte *)"BODY")) && (!File_error) ) - { - Read_dword_be(LBM_file,&image_size); - //swab((char *)&header.Width ,(char *)&Main_image_width,2); - //swab((char *)&header.Height,(char *)&Main_image_height,2); - Main_image_width = header.Width; - Main_image_height = header.Height; - - //swab((char *)&header.X_screen,(char *)&Original_screen_X,2); - //swab((char *)&header.Y_screen,(char *)&Original_screen_Y,2); - Original_screen_X = header.X_screen; - Original_screen_Y = header.Y_screen; - - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_LBM,PIXEL_SIMPLE); - if (File_error==0) - { - if (!memcmp(format,"ILBM",4)) // "ILBM": InterLeaved BitMap - { - // Calcul de la taille d'une ligne ILBM (pour les images ayant des dimensions exotiques) - if (Main_image_width & 15) - { - real_line_size=( (Main_image_width+16) >> 4 ) << 4; - line_size=( (Main_image_width+16) >> 4 )*(header.BitPlanes<<1); - } - else - { - real_line_size=Main_image_width; - line_size=(Main_image_width>>3)*header.BitPlanes; - } - - if (!header.Compression) - { // non compressé - LBM_buffer=(byte *)malloc(line_size); - for (y_pos=0; ((y_pos 127 alors il faut répéter 256-'temp_byte' fois la couleur de l'octet suivant - // Si temp_byte <= 127 alors il faut afficher directement les 'temp_byte' octets suivants - if (temp_byte>127) - { - if(Read_byte(LBM_file, &color)!=1) - { - File_error=2; - break; - } - b256=(short)(256-temp_byte); - for (counter=0; counter<=b256; counter++) - if (x_pos=line_size || Read_byte(LBM_file, &(LBM_buffer[x_pos++]))!=1) - File_error=2; - } - if (!File_error) - Draw_ILBM_line(y_pos,real_line_size); - } - - free(LBM_buffer); - /*Close_lecture();*/ - } - } - else // "PBM ": Planar(?) BitMap - { - real_line_size=Main_image_width+(Main_image_width&1); - - if (!header.Compression) - { // non compressé - LBM_buffer=(byte *)malloc(real_line_size); - for (y_pos=0; ((y_pos127) - { - if(Read_byte(LBM_file, &color)!=1) - { - File_error=2; - break; - } - b256=256-temp_byte; - for (counter=0; counter<=b256; counter++) - Pixel_load_function(x_pos++,y_pos,color); - } - else - for (counter=0; counter<=temp_byte; counter++) - { - byte byte_read=0; - if(Read_byte(LBM_file, &byte_read)!=1) - { - File_error=2; - break; - } - Pixel_load_function(x_pos++,y_pos,byte_read); - } - } - } - /*Close_lecture();*/ - } - } - } - } - else - Set_file_error(2); - } - else - { - File_error=1; - } - } - else - Set_file_error(1); - } - else - File_error=1; - } - else - File_error=1; - - fclose(LBM_file); - } - else - File_error=1; -} - - -// -- Sauver un fichier au format LBM --------------------------------------- - - byte LBM_color_list[129]; - word LBM_list_size; - byte LBM_repetition_mode; - - // ------------- Ecrire les couleurs que l'on vient de traiter ------------ - void Transfer_colors(void) - { - byte index; - - if (LBM_list_size>0) - { - if (LBM_repetition_mode) - { - Write_one_byte(LBM_file,257-LBM_list_size); - Write_one_byte(LBM_file,LBM_color_list[0]); - } - else - { - Write_one_byte(LBM_file,LBM_list_size-1); - for (index=0; index et on a 3 couleurs qui se suivent - { - LBM_list_size-=2; - Transfer_colors(); - LBM_color_list[0]=color; - LBM_color_list[1]=color; - LBM_color_list[2]=color; - LBM_list_size=3; - LBM_repetition_mode=1; - } - } - else // La couleur n'est pas la même que la précédente - { - if (!LBM_repetition_mode) // On conserve le mode... - { - LBM_color_list[LBM_list_size++]=color; - if (LBM_list_size==128) - Transfer_colors(); - } - else // On change de mode... - { - Transfer_colors(); - LBM_color_list[LBM_list_size]=color; - LBM_list_size++; - } - } - } - } - - -void Save_LBM(void) -{ - char filename[MAX_PATH_CHARACTERS]; - T_LBM_Header header; - word x_pos; - word y_pos; - byte temp_byte; - word real_width; - int file_size; - - File_error=0; - Get_full_filename(filename,0); - - // Ouverture du fichier - if ((LBM_file=fopen(filename,"wb"))) - { - Write_bytes(LBM_file,"FORM",4); - Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin - - Write_bytes(LBM_file,"PBM BMHD",8); - Write_dword_be(LBM_file,20); - - // On corrige la largeur de l'image pour qu'elle soit multiple de 2 - real_width=Main_image_width+(Main_image_width&1); - - //swab((byte *)&real_width,(byte *)&header.Width,2); - header.Width=Main_image_width; - header.Height=Main_image_height; - header.X_org=0; - header.Y_org=0; - header.BitPlanes=8; - header.Mask=0; - header.Compression=1; - header.Pad1=0; - header.Transp_col=Back_color; - header.X_aspect=1; - header.Y_aspect=1; - header.X_screen = Screen_width; - header.Y_screen = Screen_height; - - Write_word_be(LBM_file,header.Width); - Write_word_be(LBM_file,header.Height); - Write_word_be(LBM_file,header.X_org); - Write_word_be(LBM_file,header.Y_org); - Write_bytes(LBM_file,&header.BitPlanes,1); - Write_bytes(LBM_file,&header.Mask,1); - Write_bytes(LBM_file,&header.Compression,1); - Write_bytes(LBM_file,&header.Pad1,1); - Write_word_be(LBM_file,header.Transp_col); - Write_bytes(LBM_file,&header.X_aspect,1); - Write_bytes(LBM_file,&header.Y_aspect,1); - Write_word_be(LBM_file,header.X_screen); - Write_word_be(LBM_file,header.Y_screen); - - Write_bytes(LBM_file,"CMAP",4); - Write_dword_be(LBM_file,sizeof(T_Palette)); - - Write_bytes(LBM_file,Main_palette,sizeof(T_Palette)); - - Write_bytes(LBM_file,"BODY",4); - Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin - - Init_write_buffer(); - - LBM_list_size=0; - - for (y_pos=0; ((y_pos on efface le fichier - remove(filename); - } - else - File_error=1; -} - - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// BMP //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -#pragma pack(1) -typedef struct -{ - word Signature; // ='BM' = 0x4D42 - dword Size_1; // =Taille du fichier - word Reserved_1; // =0 - word Reserved_2; // =0 - dword Offset; // Nb octets avant les données bitmap - - dword Size_2; // =40 - dword Width; - dword Height; - word Planes; // =1 - word Nb_bits; // =1,4,8 ou 24 - dword Compression; - dword Size_3; - dword XPM; - dword YPM; - dword Nb_Clr; - dword Clr_Imprt; -} T_BMP_Header; -#pragma pack() - -// -- Tester si un fichier est au format BMP -------------------------------- -void Test_BMP(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - T_BMP_Header header; - - File_error=1; - Get_full_filename(filename,0); - - if ((file=fopen(filename, "rb"))) - { - if (Read_bytes(file,&(header.Signature),2) // "BM" - && Read_dword_le(file,&(header.Size_1)) - && Read_word_le(file,&(header.Reserved_1)) - && Read_word_le(file,&(header.Reserved_2)) - && Read_dword_le(file,&(header.Offset)) - && Read_dword_le(file,&(header.Size_2)) - && Read_dword_le(file,&(header.Width)) - && Read_dword_le(file,&(header.Height)) - && Read_word_le(file,&(header.Planes)) - && Read_word_le(file,&(header.Nb_bits)) - && Read_dword_le(file,&(header.Compression)) - && Read_dword_le(file,&(header.Size_3)) - && Read_dword_le(file,&(header.XPM)) - && Read_dword_le(file,&(header.YPM)) - && Read_dword_le(file,&(header.Nb_Clr)) - && Read_dword_le(file,&(header.Clr_Imprt)) - ) - { - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - header.Signature = SDL_Swap16(header.Signature); -#endif - - if ( (header.Signature==0x4D42) && (header.Size_2==40) - && header.Width && header.Height ) - File_error=0; - } - fclose(file); - } -} - -// Find the 8 important bits in a dword -byte Bitmap_mask(dword pixel, dword mask) -{ - byte result; - int i; - int bits_found; - - switch(mask) - { - // Shortcuts to quickly handle the common 24/32bit cases - case 0x000000FF: - return (pixel & 0x000000FF); - case 0x0000FF00: - return (pixel & 0x0000FF00)>>8; - case 0x00FF0000: - return (pixel & 0x00FF0000)>>16; - case 0xFF000000: - return (pixel & 0xFF000000)>>24; - } - // Uncommon : do it bit by bit. - bits_found=0; - result=0; - // Process the mask from low to high bit - for (i=0;i<32;i++) - { - // Found a bit in the mask - if (mask & (1<=8) - return result; - } - } - // Less than 8 bits in the mask: scale the result to 8 bits - return result << (8-bits_found); -} - -// -- Charger un fichier au format BMP -------------------------------------- -void Load_BMP(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - T_BMP_Header header; - byte * buffer; - word index; - byte local_palette[256][4]; // R,G,B,0 - word nb_colors = 0; - short x_pos; - short y_pos; - word line_size; - byte a,b,c=0; - long file_size; - - Get_full_filename(filename,0); - - File_error=0; - - if ((file=fopen(filename, "rb"))) - { - file_size=File_length_file(file); - - if (Read_word_le(file,&(header.Signature)) - && Read_dword_le(file,&(header.Size_1)) - && Read_word_le(file,&(header.Reserved_1)) - && Read_word_le(file,&(header.Reserved_2)) - && Read_dword_le(file,&(header.Offset)) - && Read_dword_le(file,&(header.Size_2)) - && Read_dword_le(file,&(header.Width)) - && Read_dword_le(file,&(header.Height)) - && Read_word_le(file,&(header.Planes)) - && Read_word_le(file,&(header.Nb_bits)) - && Read_dword_le(file,&(header.Compression)) - && Read_dword_le(file,&(header.Size_3)) - && Read_dword_le(file,&(header.XPM)) - && Read_dword_le(file,&(header.YPM)) - && Read_dword_le(file,&(header.Nb_Clr)) - && Read_dword_le(file,&(header.Clr_Imprt)) - ) - { - switch (header.Nb_bits) - { - case 1 : - case 4 : - case 8 : - if (header.Nb_Clr) - nb_colors=header.Nb_Clr; - else - nb_colors=1<>3; - - buffer=(byte *)malloc(line_size); - for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) - { - if (Read_bytes(file,buffer,line_size)) - for (x_pos=0; x_pos>1] & 0xF); - else - Pixel_load_function(x_pos,y_pos,buffer[x_pos>>1] >> 4 ); - break; - case 1 : - if ( buffer[x_pos>>3] & (0x80>>(x_pos&7)) ) - Pixel_load_function(x_pos,y_pos,1); - else - Pixel_load_function(x_pos,y_pos,0); - } - else - File_error=2; - } - free(buffer); - break; - - case 1 : // Compression RLE 8 bits - x_pos=0; - y_pos=Main_image_height-1; - - /*Init_lecture();*/ - if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) - File_error=2; - while (!File_error) - { - if (a) // Encoded mode - for (index=1; index<=a; index++) - Pixel_load_function(x_pos++,y_pos,b); - else // Absolute mode - switch (b) - { - case 0 : // End of line - x_pos=0; - y_pos--; - break; - case 1 : // End of bitmap - break; - case 2 : // Delta - if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) - File_error=2; - x_pos+=a; - y_pos-=b; - break; - default: // Nouvelle série - while (b) - { - if(Read_byte(file, &a)!=1) - File_error=2; - //Read_one_byte(file, &c); - Pixel_load_function(x_pos++,y_pos,a); - //if (--c) - //{ - // Pixel_load_function(x_pos++,y_pos,c); - // b--; - //} - b--; - } - if (ftell(file) & 1) fseek(file, 1, SEEK_CUR); - } - if (a==0 && b==1) - break; - if(Read_byte(file, &a) !=1 || Read_byte(file, &b)!=1) - { - File_error=2; - } - } - /*Close_lecture();*/ - break; - - case 2 : // Compression RLE 4 bits - x_pos=0; - y_pos=Main_image_height-1; - - /*Init_lecture();*/ - if(Read_byte(file, &a)!=1 || Read_byte(file, &b) != 1) - File_error =2; - while ( (!File_error) && ((a)||(b!=1)) ) - { - if (a) // Encoded mode (A fois les 1/2 pixels de B) - for (index=1; index<=a; index++) - { - if (index & 1) - Pixel_load_function(x_pos,y_pos,b>>4); - else - Pixel_load_function(x_pos,y_pos,b&0xF); - x_pos++; - } - else // Absolute mode - switch (b) - { - case 0 : //End of line - x_pos=0; - y_pos--; - break; - case 1 : // End of bitmap - break; - case 2 : // Delta - if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) - File_error=2; - x_pos+=a; - y_pos-=b; - break; - default: // Nouvelle série (B 1/2 pixels bruts) - for (index=1; ((index<=b) && (!File_error)); index++,x_pos++) - { - if (index&1) - { - if(Read_byte(file, &c)!=1) File_error=2; - Pixel_load_function(x_pos,y_pos,c>>4); - } - else - Pixel_load_function(x_pos,y_pos,c&0xF); - } - // On lit l'octet rendant le nombre d'octets pair, si - // nécessaire. Encore un truc de crétin "made in MS". - if ( ((b&3)==1) || ((b&3)==2) ) - { - byte dummy; - if(Read_byte(file, &dummy)!=1) File_error=2; - } - } - if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) File_error=2; - } - /*Close_lecture();*/ - } - fclose(file); - } - else - { - fclose(file); - File_error=1; - } - } - } - else - { - // Image 16/24/32 bits - dword red_mask; - dword green_mask; - dword blue_mask; - if (header.Nb_bits == 16) - { - red_mask = 0x00007C00; - green_mask = 0x000003E0; - blue_mask = 0x0000001F; - } - else - { - red_mask = 0x00FF0000; - green_mask = 0x0000FF00; - blue_mask = 0x000000FF; - } - File_error=0; - - Main_image_width=header.Width; - Main_image_height=header.Height; - Init_preview_24b(header.Width,header.Height,file_size,FORMAT_BMP); - if (File_error==0) - { - switch (header.Compression) - { - case 3: // BI_BITFIELDS - if (!Read_dword_le(file,&red_mask) || - !Read_dword_le(file,&green_mask) || - !Read_dword_le(file,&blue_mask)) - File_error=2; - break; - default: - break; - } - if (fseek(file, header.Offset, SEEK_SET)) - File_error=2; - } - if (File_error==0) - { - switch (header.Nb_bits) - { - // 24bit bitmap - default: - case 24: - line_size=Main_image_width*3; - x_pos=(line_size % 4); // x_pos sert de variable temporaire - if (x_pos>0) - line_size+=(4-x_pos); - - buffer=(byte *)malloc(line_size); - for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) - { - if (Read_bytes(file,buffer,line_size)) - for (x_pos=0,index=0; x_pos=0) && (!File_error)); y_pos--) - { - if (Read_bytes(file,buffer,line_size)) - for (x_pos=0; x_pos=0) && (!File_error)); y_pos--) - { - if (Read_bytes(file,buffer,line_size)) - for (x_pos=0; x_pos> 3)+1) << 3; - else - line_size=Main_image_width; - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - header.Signature = 0x424D; -#else - header.Signature = 0x4D42; -#endif - header.Size_1 =(line_size*Main_image_height)+1078; - header.Reserved_1 =0; - header.Reserved_2 =0; - header.Offset =1078; - header.Size_2 =40; - header.Width =Main_image_width; - header.Height =Main_image_height; - header.Planes =1; - header.Nb_bits =8; - header.Compression=0; - header.Size_3 =0; - header.XPM =0; - header.YPM =0; - header.Nb_Clr =0; - header.Clr_Imprt =0; - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - header.Size_1 = SDL_Swap32( header.Size_1 ); - header.Offset = SDL_Swap32( header.Offset ); - header.Size_2 = SDL_Swap32( header.Size_2 ); - header.Width = SDL_Swap32( header.Width ); - header.Height = SDL_Swap32( header.Height ); - header.Planes = SDL_Swap16( header.Planes ); - header.Nb_bits = SDL_Swap16( header.Nb_bits ); - // If you ever set any more fields to non-zero, please swap here! -#endif - - if (Write_bytes(file,&header,sizeof(T_BMP_Header))) - { - // Chez Bill, ils ont dit: "On va mettre les couleur dans l'ordre - // inverse, et pour faire chier, on va les mettre sur une échelle de - // 0 à 255 parce que le standard VGA c'est de 0 à 63 (logique!). Et - // puis comme c'est pas assez débile, on va aussi y rajouter un octet - // toujours à 0 pour forcer les gens à s'acheter des gros disques - // durs... Comme ça, ça fera passer la pillule lorsqu'on sortira - // Windows 95." ... - for (index=0; index<256; index++) - { - local_palette[index][0]=Main_palette[index].B; - local_palette[index][1]=Main_palette[index].G; - local_palette[index][2]=Main_palette[index].R; - local_palette[index][3]=0; - } - - if (Write_bytes(file,local_palette,1024)) - { - Init_write_buffer(); - - // ... Et Bill, il a dit: "OK les gars! Mais seulement si vous rangez - // les pixels dans l'ordre inverse, mais que sur les Y quand-même - // parce que faut pas pousser." - for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) - for (x_pos=0; x_pos>=current_nb_bits; - nb_bits_processed +=current_nb_bits; - nb_bits_to_process-=current_nb_bits; - GIF_remainder_bits -=current_nb_bits; - } - - return GIF_current_code; - } - - // -- Affiche un nouveau pixel -- - - void GIF_new_pixel(byte color) - { - Pixel_load_function(GIF_pos_X,GIF_pos_Y,color); - - GIF_pos_X++; - - if (GIF_pos_X>=Main_image_width) - { - GIF_pos_X=0; - - if (!GIF_interlaced) - GIF_pos_Y++; - else - { - switch (GIF_pass) - { - case 0 : GIF_pos_Y+=8; - break; - case 1 : GIF_pos_Y+=8; - break; - case 2 : GIF_pos_Y+=4; - break; - default: GIF_pos_Y+=2; - } - - if (GIF_pos_Y>=Main_image_height) - { - switch(++GIF_pass) - { - case 1 : GIF_pos_Y=4; - break; - case 2 : GIF_pos_Y=2; - break; - case 3 : GIF_pos_Y=1; - break; - case 4 : GIF_finished_interlaced_image=1; - } - } - } - } - } - - -void Load_GIF(void) -{ - char filename[MAX_PATH_CHARACTERS]; - char signature[6]; - - word * alphabet_stack; // Pile de décodage d'une chaîne - word * alphabet_prefix; // Table des préfixes des codes - word * alphabet_suffix; // Table des suffixes des codes - word alphabet_free; // Position libre dans l'alphabet - word alphabet_max; // Nombre d'entrées possibles dans l'alphabet - word alphabet_stack_pos; // Position dans la pile de décodage d'un chaîne - - T_GIF_LSDB LSDB; - T_GIF_IDB IDB; - - word nb_colors; // Nombre de couleurs dans l'image - word color_index; // index de traitement d'une couleur - byte size_to_read; // Nombre de données à lire (divers) - byte block_indentifier; // Code indicateur du type de bloc en cours - word initial_nb_bits; // Nb de bits au début du traitement LZW - word special_case=0; // Mémoire pour le cas spécial - word old_code=0; // Code précédent - word byte_read; // Sauvegarde du code en cours de lecture - word value_clr; // Valeur <=> Clear tables - word value_eof; // Valeur <=> End d'image - long file_size; - int number_LID; // Nombre d'images trouvées dans le fichier - - /////////////////////////////////////////////////// FIN DES DECLARATIONS // - - - GIF_pos_X=0; - GIF_pos_Y=0; - GIF_last_byte=0; - GIF_remainder_bits=0; - GIF_remainder_byte=0; - number_LID=0; - - Get_full_filename(filename,0); - - if ((GIF_file=fopen(filename, "rb"))) - { - file_size=File_length_file(GIF_file); - if ( (Read_bytes(GIF_file,signature,6)) && - ( (memcmp(signature,"GIF87a",6)==0) || - (memcmp(signature,"GIF89a",6)==0) ) ) - { - - // Allocation de mémoire pour les tables & piles de traitement: - alphabet_stack =(word *)malloc(4096*sizeof(word)); - alphabet_prefix=(word *)malloc(4096*sizeof(word)); - alphabet_suffix=(word *)malloc(4096*sizeof(word)); - - if (Read_word_le(GIF_file,&(LSDB.Width)) - && Read_word_le(GIF_file,&(LSDB.Height)) - && Read_byte(GIF_file,&(LSDB.Resol)) - && Read_byte(GIF_file,&(LSDB.Backcol)) - && Read_byte(GIF_file,&(LSDB.Aspect)) - ) - { - // Lecture du Logical Screen Descriptor Block réussie: - - Original_screen_X=LSDB.Width; - Original_screen_Y=LSDB.Height; - - // Palette globale dispo = (LSDB.Resol and $80) - // Profondeur de couleur =((LSDB.Resol and $70) shr 4)+1 - // Nombre de bits/pixel = (LSDB.Resol and $07)+1 - // Ordre de Classement = (LSDB.Aspect and $80) - - alphabet_stack_pos=0; - GIF_last_byte =0; - GIF_remainder_bits =0; - GIF_remainder_byte =0; - - nb_colors=(1 << ((LSDB.Resol & 0x07)+1)); - initial_nb_bits=(LSDB.Resol & 0x07)+2; - - if (LSDB.Resol & 0x80) - { - // Palette globale dispo: - - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - - // On peut maintenant charger la nouvelle palette: - if (!(LSDB.Aspect & 0x80)) - // Palette dans l'ordre: - for(color_index=0;color_indexnb_char_to_keep) - fseek(GIF_file,size_to_read-nb_char_to_keep,SEEK_CUR); - } - break; - case 0xF9: // Graphics Control Extension - // Prévu pour la transparence - - default: - // On saute le bloc: - fseek(GIF_file,size_to_read,SEEK_CUR); - break; - } - // Lecture de la taille du bloc suivant: - Read_byte(GIF_file,&size_to_read); - } - } - break; - case 0x2C: // Local Image Descriptor - { - // Si on a deja lu une image, c'est une GIF animée ou bizarroide, on sort. - if (number_LID!=0) - { - File_error=2; - break; - } - number_LID++; - - // lecture de 10 derniers octets - if ( Read_word_le(GIF_file,&(IDB.Pos_X)) - && Read_word_le(GIF_file,&(IDB.Pos_Y)) - && Read_word_le(GIF_file,&(IDB.Image_width)) - && Read_word_le(GIF_file,&(IDB.Image_height)) - && Read_byte(GIF_file,&(IDB.Indicator)) - && Read_byte(GIF_file,&(IDB.Nb_bits_pixel)) - && IDB.Image_width && IDB.Image_height) - { - Main_image_width=IDB.Image_width; - Main_image_height=IDB.Image_height; - - Init_preview(IDB.Image_width,IDB.Image_height,file_size,FORMAT_GIF,PIXEL_SIMPLE); - - // Palette locale dispo = (IDB.Indicator and $80) - // Image entrelacée = (IDB.Indicator and $40) - // Ordre de classement = (IDB.Indicator and $20) - // Nombre de bits/pixel = (IDB.Indicator and $07)+1 (si palette locale dispo) - - if (IDB.Indicator & 0x80) - { - // Palette locale dispo - - nb_colors=(1 << ((IDB.Indicator & 0x07)+1)); - initial_nb_bits=(IDB.Indicator & 0x07)+2; - - if (!(IDB.Indicator & 0x40)) - // Palette dans l'ordre: - for(color_index=0;color_indexvalue_clr) - { - alphabet_stack[alphabet_stack_pos++]=alphabet_suffix[GIF_current_code]; - GIF_current_code=alphabet_prefix[GIF_current_code]; - } - - special_case=alphabet_stack[alphabet_stack_pos++]=GIF_current_code; - - do - GIF_new_pixel(alphabet_stack[--alphabet_stack_pos]); - while (alphabet_stack_pos!=0); - - alphabet_prefix[alphabet_free ]=old_code; - alphabet_suffix[alphabet_free++]=GIF_current_code; - old_code=byte_read; - - if (alphabet_free>alphabet_max) - { - if (GIF_nb_bits<12) - alphabet_max =((1 << (++GIF_nb_bits))-1); - } - } - else // Code Clear rencontré - { - GIF_nb_bits =initial_nb_bits; - alphabet_max =((1 << GIF_nb_bits)-1); - alphabet_free =nb_colors+2; - special_case =GIF_get_next_code(); - old_code =GIF_current_code; - GIF_new_pixel(GIF_current_code); - } - } - else - File_error=2; - } // Code End-Of-Information ou erreur de fichier rencontré - - /*Close_lecture();*/ - - if (File_error>=0) - if ( /* (GIF_pos_X!=0) || */ - ( ( (!GIF_interlaced) && (GIF_pos_Y!=Main_image_height) ) || - ( (GIF_interlaced) && (!GIF_finished_interlaced_image) ) - ) ) - File_error=2; - } // Le fichier contenait un IDB - else - File_error=2; - } - default: - break; - } - // Lecture du code de fonction suivant: - Read_byte(GIF_file,&block_indentifier); - } - } // Le fichier contenait un LSDB - else - File_error=1; - - // Libération de la mémoire utilisée par les tables & piles de traitement: - free(alphabet_suffix); - free(alphabet_prefix); - free(alphabet_stack); - } // Le fichier contenait au moins la signature GIF87a ou GIF89a - else - File_error=1; - - fclose(GIF_file); - - } // Le fichier était ouvrable - else - File_error=1; -} - - -// -- Sauver un fichier au format GIF --------------------------------------- - - int GIF_stop; // "On peut arrêter la sauvegarde du fichier" - byte GIF_buffer[256]; // buffer d'écriture de bloc de données compilées - - // -- Vider le buffer GIF dans le buffer KM -- - - void GIF_empty_buffer(void) - { - word index; - - if (GIF_remainder_byte) - { - GIF_buffer[0]=GIF_remainder_byte; - - for (index=0;index<=GIF_remainder_byte;index++) - Write_one_byte(GIF_file,GIF_buffer[index]); - - GIF_remainder_byte=0; - } - } - - // -- Ecrit un code à GIF_nb_bits -- - - void GIF_set_code(word Code) - { - word nb_bits_to_process=GIF_nb_bits; - word nb_bits_processed =0; - word current_nb_bits; - - while (nb_bits_to_process) - { - current_nb_bits=(nb_bits_to_process<=(8-GIF_remainder_bits))?nb_bits_to_process:(8-GIF_remainder_bits); - - GIF_last_byte|=(Code & ((1<>=current_nb_bits; - GIF_remainder_bits +=current_nb_bits; - nb_bits_processed +=current_nb_bits; - nb_bits_to_process-=current_nb_bits; - - if (GIF_remainder_bits==8) // Il ne reste plus de bits à coder sur l'octet courant - { - // Ecrire l'octet à balancer: - GIF_buffer[++GIF_remainder_byte]=GIF_last_byte; - - // Si on a atteint la fin du bloc de Raster Data - if (GIF_remainder_byte==255) - // On doit vider le buffer qui est maintenant plein - GIF_empty_buffer(); - - GIF_last_byte=0; - GIF_remainder_bits=0; - } - } - } - - - // -- Lire le pixel suivant -- - - byte GIF_next_pixel(void) - { - byte temp; - - temp=Read_pixel_function(GIF_pos_X,GIF_pos_Y); - - if (++GIF_pos_X>=Main_image_width) - { - GIF_pos_X=0; - if (++GIF_pos_Y>=Main_image_height) - GIF_stop=1; - } - - return temp; - } - - - -void Save_GIF(void) -{ - char filename[MAX_PATH_CHARACTERS]; - - word * alphabet_prefix; // Table des préfixes des codes - word * alphabet_suffix; // Table des suffixes des codes - word * alphabet_daughter; // Table des chaînes filles (plus longues) - word * alphabet_sister; // Table des chaînes soeurs (même longueur) - word alphabet_free; // Position libre dans l'alphabet - word alphabet_max; // Nombre d'entrées possibles dans l'alphabet - word start; // Code précédent (sert au linkage des chaînes) - int descend; // Booléen "On vient de descendre" - - T_GIF_LSDB LSDB; - T_GIF_IDB IDB; - - - byte block_indentifier; // Code indicateur du type de bloc en cours - word current_string; // Code de la chaîne en cours de traitement - byte current_char; // Caractère à coder - word index; // index de recherche de chaîne - - - /////////////////////////////////////////////////// FIN DES DECLARATIONS // - - - GIF_pos_X=0; - GIF_pos_Y=0; - GIF_last_byte=0; - GIF_remainder_bits=0; - GIF_remainder_byte=0; - - Get_full_filename(filename,0); - - if ((GIF_file=fopen(filename,"wb"))) - { - // On écrit la signature du fichier - if (Write_bytes(GIF_file,"GIF89a",6)) - { - // La signature du fichier a été correctement écrite. - - // Allocation de mémoire pour les tables - alphabet_prefix=(word *)malloc(4096*sizeof(word)); - alphabet_suffix=(word *)malloc(4096*sizeof(word)); - alphabet_daughter =(word *)malloc(4096*sizeof(word)); - alphabet_sister =(word *)malloc(4096*sizeof(word)); - - // On initialise le LSDB du fichier - if (Config.Screen_size_in_GIF) - { - LSDB.Width=Screen_width; - LSDB.Height=Screen_height; - } - else - { - LSDB.Width=Main_image_width; - LSDB.Height=Main_image_height; - } - LSDB.Resol =0x97; // Image en 256 couleurs, avec une palette - LSDB.Backcol=0; - LSDB.Aspect =0; // Palette normale - - // On sauve le LSDB dans le fichier - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - LSDB.Width = SDL_Swap16(LSDB.Width); - LSDB.Height = SDL_Swap16(LSDB.Height); -#endif - - if (Write_bytes(GIF_file,&LSDB,sizeof(T_GIF_LSDB))) - { - // Le LSDB a été correctement écrit. - - // On sauve la palette - if (Write_bytes(GIF_file,Main_palette,768)) - { - // La palette a été correctement écrite. - - // Le jour où on se servira des blocks d'extensions pour placer - // des commentaires, on le fera ici. - - // Ecriture de la transparence - //Write_bytes(GIF_file,"\x21\xF9\x04\x01\x00\x00\xNN\x00",8); - - // Ecriture du commentaire - if (Main_comment[0]) - { - Write_bytes(GIF_file,"\x21\xFE",2); - Write_byte(GIF_file,strlen(Main_comment)); - Write_bytes(GIF_file,Main_comment,strlen(Main_comment)+1); - } - - - - // On va écrire un block indicateur d'IDB et l'IDB du fichier - - block_indentifier=0x2C; - IDB.Pos_X=0; - IDB.Pos_Y=0; - IDB.Image_width=Main_image_width; - IDB.Image_height=Main_image_height; - IDB.Indicator=0x07; // Image non entrelacée, pas de palette locale. - IDB.Nb_bits_pixel=8; // Image 256 couleurs; - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - IDB.Image_width = SDL_Swap16(IDB.Image_width); - IDB.Image_height = SDL_Swap16(IDB.Image_height); -#endif - - if ( Write_bytes(GIF_file,&block_indentifier,1) && - Write_bytes(GIF_file,&IDB,sizeof(T_GIF_IDB)) ) - { - // Le block indicateur d'IDB et l'IDB ont étés correctements - // écrits. - - Init_write_buffer(); - - index=4096; - File_error=0; - GIF_stop=0; - - // Réintialisation de la table: - alphabet_free=258; - GIF_nb_bits =9; - alphabet_max =511; - GIF_set_code(256); - for (start=0;start<4096;start++) - { - alphabet_daughter[start]=4096; - alphabet_sister[start]=4096; - } - - ////////////////////////////////////////////// COMPRESSION LZW // - - start=current_string=GIF_next_pixel(); - descend=1; - - do - { - current_char=GIF_next_pixel(); - - // On regarde si dans la table on aurait pas une chaîne - // équivalente à current_string+Caractere - - while ( (index0xFFF) - { - // Réintialisation de la table: - GIF_set_code(256); - alphabet_free=258; - GIF_nb_bits =9; - alphabet_max =511; - for (start=0;start<4096;start++) - { - alphabet_daughter[start]=4096; - alphabet_sister[start]=4096; - } - } - else if (alphabet_free>alphabet_max+1) - { - // On augmente le nb de bits - - GIF_nb_bits++; - alphabet_max=(1< 16c , 1 => 256c , ... - word Bytes_per_plane_line;// Doit toujours être pair - word Palette_info; // 1 => color , 2 => Gris (ignoré à partir de la version 4) - word Screen_X; // |_ Dimensions de - word Screen_Y; // | l'écran d'origine - byte Filler[54]; // Ca... J'adore! - } T_PCX_Header; -#pragma pack() - -T_PCX_Header PCX_header; - -// -- Tester si un fichier est au format PCX -------------------------------- - -void Test_PCX(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - - File_error=0; - Get_full_filename(filename,0); - - if ((file=fopen(filename, "rb"))) - { - if (Read_byte(file,&(PCX_header.Manufacturer)) && - Read_byte(file,&(PCX_header.Version)) && - Read_byte(file,&(PCX_header.Compression)) && - Read_byte(file,&(PCX_header.Depth)) && - Read_word_le(file,&(PCX_header.X_min)) && - Read_word_le(file,&(PCX_header.Y_min)) && - Read_word_le(file,&(PCX_header.X_max)) && - Read_word_le(file,&(PCX_header.Y_max)) && - Read_word_le(file,&(PCX_header.X_dpi)) && - Read_word_le(file,&(PCX_header.Y_dpi)) && - Read_bytes(file,&(PCX_header.Palette_16c),48) && - Read_byte(file,&(PCX_header.Reserved)) && - Read_byte(file,&(PCX_header.Plane)) && - Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) && - Read_word_le(file,&(PCX_header.Palette_info)) && - Read_word_le(file,&(PCX_header.Screen_X)) && - Read_word_le(file,&(PCX_header.Screen_Y)) && - Read_bytes(file,&(PCX_header.Filler),54) ) - { - - // Vu que ce header a une signature de merde et peu significative, il - // va falloir que je teste différentes petites valeurs dont je connais - // l'intervalle. Grrr! - if ( (PCX_header.Manufacturer!=10) - || (PCX_header.Compression>1) - || ( (PCX_header.Depth!=1) && (PCX_header.Depth!=2) && (PCX_header.Depth!=4) && (PCX_header.Depth!=8) ) - || ( (PCX_header.Plane!=1) && (PCX_header.Plane!=2) && (PCX_header.Plane!=4) && (PCX_header.Plane!=8) && (PCX_header.Plane!=3) ) - || (PCX_header.X_max>((reduction_minus_one-(x_pos%reduction))*depth)) & byte_mask; - Pixel_load_function(x_pos,y_pos,color); - } - } - -void Load_PCX(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - - short line_size; - short real_line_size; // width de l'image corrigée - short width_read; - short x_pos; - short y_pos; - byte byte1; - byte byte2; - byte index; - dword nb_colors; - long file_size; - byte palette_CGA[9]={ 84,252,252, 252, 84,252, 252,252,252}; - - long position; - long image_size; - byte * buffer; - - Get_full_filename(filename,0); - - File_error=0; - - if ((file=fopen(filename, "rb"))) - { - file_size=File_length_file(file); - /* - if (Read_bytes(file,&PCX_header,sizeof(T_PCX_Header))) - {*/ - - if (Read_byte(file,&(PCX_header.Manufacturer)) && - Read_byte(file,&(PCX_header.Version)) && - Read_byte(file,&(PCX_header.Compression)) && - Read_byte(file,&(PCX_header.Depth)) && - Read_word_le(file,&(PCX_header.X_min)) && - Read_word_le(file,&(PCX_header.Y_min)) && - Read_word_le(file,&(PCX_header.X_max)) && - Read_word_le(file,&(PCX_header.Y_max)) && - Read_word_le(file,&(PCX_header.X_dpi)) && - Read_word_le(file,&(PCX_header.Y_dpi)) && - Read_bytes(file,&(PCX_header.Palette_16c),48) && - Read_byte(file,&(PCX_header.Reserved)) && - Read_byte(file,&(PCX_header.Plane)) && - Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) && - Read_word_le(file,&(PCX_header.Palette_info)) && - Read_word_le(file,&(PCX_header.Screen_X)) && - Read_word_le(file,&(PCX_header.Screen_Y)) && - Read_bytes(file,&(PCX_header.Filler),54) ) - { - - Main_image_width=PCX_header.X_max-PCX_header.X_min+1; - Main_image_height=PCX_header.Y_max-PCX_header.Y_min+1; - - Original_screen_X=PCX_header.Screen_X; - Original_screen_Y=PCX_header.Screen_Y; - - if (PCX_header.Plane!=3) - { - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_PCX,PIXEL_SIMPLE); - if (File_error==0) - { - // On prépare la palette à accueillir les valeurs du fichier PCX - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - nb_colors=(dword)(1<4) - memcpy(Main_palette,PCX_header.Palette_16c,48); - else - { - Main_palette[1].R=0; - Main_palette[1].G=0; - Main_palette[1].B=0; - byte1=PCX_header.Palette_16c[3]>>5; - if (nb_colors==4) - { // Pal. CGA "alakon" (du Turc Allahkoum qui signifie "à la con" :)) - memcpy(Main_palette+1,palette_CGA,9); - if (!(byte1&2)) - { - Main_palette[1].B=84; - Main_palette[2].B=84; - Main_palette[3].B=84; - } - } // Palette monochrome (on va dire que c'est du N&B) - else - { - Main_palette[1].R=252; - Main_palette[1].G=252; - Main_palette[1].B=252; - } - } - - // On se positionne à la fin du fichier - 769 octets pour voir s'il y - // a une palette. - if ( (PCX_header.Depth==8) && (PCX_header.Version>=5) && (file_size>(256*3)) ) - { - fseek(file,file_size-((256*3)+1),SEEK_SET); - // On regarde s'il y a une palette après les données de l'image - if (Read_byte(file,&byte1)) - if (byte1==12) // Lire la palette si c'est une image en 256 couleurs - { - int index; - // On lit la palette 256c que ces crétins ont foutue à la fin du fichier - for(index=0;index<256;index++) - if ( ! Read_byte(file,&Main_palette[index].R) - || ! Read_byte(file,&Main_palette[index].G) - || ! Read_byte(file,&Main_palette[index].B) ) - { - File_error=2; - DEBUG("ERROR READING PCX PALETTE !",index); - break; - } - } - } - Set_palette(Main_palette); - Remap_fileselector(); - - // Maintenant qu'on a lu la palette que ces crétins sont allés foutre - // à la fin, on retourne juste après le header pour lire l'image. - fseek(file,128,SEEK_SET); - if (!File_error) - { - line_size=PCX_header.Bytes_per_plane_line*PCX_header.Plane; - real_line_size=(short)PCX_header.Bytes_per_plane_line<<3; - // On se sert de données LBM car le dessin de ligne en moins de 256 - // couleurs se fait comme avec la structure ILBM. - Image_HAM=0; - HBPm1=PCX_header.Plane-1; - LBM_buffer=(byte *)malloc(line_size); - - // Chargement de l'image - if (PCX_header.Compression) // Image compressée - { - /*Init_lecture();*/ - - image_size=(long)PCX_header.Bytes_per_plane_line*Main_image_height; - - if (PCX_header.Depth==8) // 256 couleurs (1 plan) - { - for (position=0; ((position=line_size) - { - for (x_pos=0; x_pos=line_size) - { - for (x_pos=0; x_pos1) || (last_pixel>=0xC0) ) - Write_one_byte(file,counter|0xC0); - Write_one_byte(file,last_pixel); - - } - } - - // Ecriture de l'octet (12) indiquant que la palette arrive - if (!File_error) - Write_one_byte(file,12); - - End_write(file); - - // Ecriture de la palette - if (!File_error) - { - if (! Write_bytes(file,Main_palette,sizeof(T_Palette))) - File_error=1; - } - } - else - File_error=1; - - fclose(file); - - if (File_error) - remove(filename); - - } - else - File_error=1; -} - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// CEL //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -#pragma pack(1) -typedef struct -{ - word Width; // width de l'image - word Height; // height de l'image -} T_CEL_Header1; - -typedef struct -{ - byte Signature[4]; // Signature du format - byte Kind; // Type de fichier ($10=PALette $20=BitMaP) - byte Nb_bits; // Nombre de bits - word Filler1; // ??? - word Width; // width de l'image - word Height; // height de l'image - word X_offset; // Offset en X de l'image - word Y_offset; // Offset en Y de l'image - byte Filler2[16]; // ??? -} T_CEL_Header2; -#pragma pack() - -// -- Tester si un fichier est au format CEL -------------------------------- - -void Test_CEL(void) -{ - char filename[MAX_PATH_CHARACTERS]; - int size; - FILE *file; - T_CEL_Header1 header1; - T_CEL_Header2 header2; - int file_size; - - File_error=0; - Get_full_filename(filename,0); - file_size=File_length(filename); - if (file_size==0) - { - File_error = 1; // Si on ne peut pas faire de stat il vaut mieux laisser tomber - return; - } - - if (! (file=fopen(filename, "rb"))) - { - File_error = 1; - return; - } - if (Read_word_le(file,&header1.Width) && - Read_word_le(file,&header1.Height) ) - { - // Vu que ce header n'a pas de signature, il va falloir tester la - // cohérence de la dimension de l'image avec celle du fichier. - - size=file_size-sizeof(T_CEL_Header1); - if ( (!size) || ( (((header1.Width+1)>>1)*header1.Height)!=size ) ) - { - // Tentative de reconnaissance de la signature des nouveaux fichiers - - fseek(file,0,SEEK_SET); - if (Read_bytes(file,&header2.Signature,4) && - !memcmp(header2.Signature,"KiSS",4) && - Read_byte(file,&header2.Kind) && - (header2.Kind==0x20) && - Read_byte(file,&header2.Nb_bits) && - Read_word_le(file,&header2.Filler1) && - Read_word_le(file,&header2.Width) && - Read_word_le(file,&header2.Height) && - Read_word_le(file,&header2.X_offset) && - Read_word_le(file,&header2.Y_offset) && - Read_bytes(file,&header2.Filler2,16)) - { - // ok - } - else - File_error=1; - } - else - File_error=1; - } - else - { - File_error=1; - } - fclose(file); -} - - -// -- Lire un fichier au format CEL ----------------------------------------- - -void Load_CEL(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - T_CEL_Header1 header1; - T_CEL_Header2 header2; - short x_pos; - short y_pos; - byte last_byte=0; - long file_size; - - File_error=0; - Get_full_filename(filename,0); - if ((file=fopen(filename, "rb"))) - { - if (Read_bytes(file,&header1,sizeof(T_CEL_Header1))) - { - file_size=File_length_file(file); - if ( (file_size>(long int)sizeof(T_CEL_Header1)) - && ( (((header1.Width+1)>>1)*header1.Height)==(file_size-(long int)sizeof(T_CEL_Header1)) ) ) - { - // Chargement d'un fichier CEL sans signature (vieux fichiers) - Main_image_width=header1.Width; - Main_image_height=header1.Height; - Original_screen_X=Main_image_width; - Original_screen_Y=Main_image_height; - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE); - if (File_error==0) - { - // Chargement de l'image - /*Init_lecture();*/ - for (y_pos=0;((y_pos> 4)); - } - else - Pixel_load_function(x_pos,y_pos,(last_byte & 15)); - /*Close_lecture();*/ - } - } - else - { - // On réessaye avec le nouveau format - - fseek(file,0,SEEK_SET); - if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) - { - // Chargement d'un fichier CEL avec signature (nouveaux fichiers) - - Main_image_width=header2.Width+header2.X_offset; - Main_image_height=header2.Height+header2.Y_offset; - Original_screen_X=Main_image_width; - Original_screen_Y=Main_image_height; - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE); - if (File_error==0) - { - // Chargement de l'image - /*Init_lecture();*/ - - if (!File_error) - { - // Effacement du décalage - for (y_pos=0;y_pos> 4)); - } - else - Pixel_load_function(x_pos+header2.X_offset,y_pos+header2.Y_offset,(last_byte & 15)); - break; - - case 8: - for (y_pos=0;((y_pos16 sont utilisées dans l'image - for (x_pos=16;((x_pos<256) && (!Utilisation[x_pos]));x_pos++); - - if (x_pos==256) - { - // Cas d'une image 16 couleurs (écriture à l'ancien format) - - header1.Width =Main_image_width; - header1.Height=Main_image_height; - - if (Write_bytes(file,&header1,sizeof(T_CEL_Header1))) - { - // Sauvegarde de l'image - Init_write_buffer(); - for (y_pos=0;((y_pos>4)!=0) - File_error=1; - } - else - { - if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) - { - if (memcmp(header2.Signature,"KiSS",4)==0) - { - if (header2.Kind!=0x10) - File_error=1; - } - else - File_error=1; - } - else - File_error=1; - } - fclose(file); - } - else - File_error=1; -} - - -// -- Lire un fichier au format KCF ----------------------------------------- - -void Load_KCF(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - T_KCF_Header buffer; - T_CEL_Header2 header2; - byte bytes[3]; - int pal_index; - int color_index; - int index; - long file_size; - - - File_error=0; - Get_full_filename(filename,0); - if ((file=fopen(filename, "rb"))) - { - file_size=File_length_file(file); - if (file_size==sizeof(T_KCF_Header)) - { - // Fichier KCF à l'ancien format - - if (Read_bytes(file,&buffer,sizeof(T_KCF_Header))) - { - // Init_preview(?); // Pas possible... pas d'image... - - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - - // Chargement de la palette - for (pal_index=0;pal_index<10;pal_index++) - for (color_index=0;color_index<16;color_index++) - { - index=16+(pal_index*16)+color_index; - Main_palette[index].R=((buffer.Palette[pal_index].color[color_index].Byte1 >> 4) << 4); - Main_palette[index].B=((buffer.Palette[pal_index].color[color_index].Byte1 & 15) << 4); - Main_palette[index].G=((buffer.Palette[pal_index].color[color_index].Byte2 & 15) << 4); - } - - for (index=0;index<16;index++) - { - Main_palette[index].R=Main_palette[index+16].R; - Main_palette[index].G=Main_palette[index+16].G; - Main_palette[index].B=Main_palette[index+16].B; - } - - Set_palette(Main_palette); - Remap_fileselector(); - } - else - File_error=1; - } - else - { - // Fichier KCF au nouveau format - - if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) - { - // Init_preview(?); // Pas possible... pas d'image... - - index=(header2.Nb_bits==12)?16:0; - for (pal_index=0;pal_index> 4) << 4; - Main_palette[index].B=(bytes[0] & 15) << 4; - Main_palette[index].G=(bytes[1] & 15) << 4; - break; - - case 24: // RRRR RRRR | VVVV VVVV | BBBB BBBB - Read_bytes(file,bytes,3); - Main_palette[index].R=bytes[0]; - Main_palette[index].G=bytes[1]; - Main_palette[index].B=bytes[2]; - } - - index++; - } - } - - if (header2.Nb_bits==12) - for (index=0;index<16;index++) - { - Main_palette[index].R=Main_palette[index+16].R; - Main_palette[index].G=Main_palette[index+16].G; - Main_palette[index].B=Main_palette[index+16].B; - } - - Set_palette(Main_palette); - Remap_fileselector(); - } - else - File_error=1; - } - fclose(file); - } - else - File_error=1; - - if (!File_error) Draw_palette_preview(); -} - - -// -- Ecrire un fichier au format KCF --------------------------------------- - -void Save_KCF(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - T_KCF_Header buffer; - T_CEL_Header2 header2; - byte bytes[3]; - int pal_index; - int color_index; - int index; - dword Utilisation[256]; // Table d'utilisation de couleurs - - // On commence par compter l'utilisation de chaque couleurs - Count_used_colors(Utilisation); - - File_error=0; - Get_full_filename(filename,0); - if ((file=fopen(filename,"wb"))) - { - // Sauvegarde de la palette - - // On regarde si des couleurs >16 sont utilisées dans l'image - for (index=16;((index<256) && (!Utilisation[index]));index++); - - if (index==256) - { - // Cas d'une image 16 couleurs (écriture à l'ancien format) - - for (pal_index=0;pal_index<10;pal_index++) - for (color_index=0;color_index<16;color_index++) - { - index=16+(pal_index*16)+color_index; - buffer.Palette[pal_index].color[color_index].Byte1=((Main_palette[index].R>>4)<<4) | (Main_palette[index].B>>4); - buffer.Palette[pal_index].color[color_index].Byte2=Main_palette[index].G>>4; - } - - if (! Write_bytes(file,&buffer,sizeof(T_KCF_Header))) - File_error=1; - } - else - { - // Cas d'une image 256 couleurs (écriture au nouveau format) - - memcpy(header2.Signature,"KiSS",4); // Initialisation de la signature - header2.Kind=0x10; // Initialisation du type (PALette) - header2.Nb_bits=24; // Initialisation du nombre de bits - header2.Filler1=0; // Initialisation du filler 1 (?) - header2.Width=256; // Initialisation du nombre de couleurs - header2.Height=1; // Initialisation du nombre de palettes - header2.X_offset=0; // Initialisation du décalage X - header2.Y_offset=0; // Initialisation du décalage Y - for (index=0;index<16;index++) // Initialisation du filler 2 (?) - header2.Filler2[index]=0; - - if (! Write_bytes(file,&header2,sizeof(T_CEL_Header2))) - File_error=1; - - for (index=0;(index<256) && (!File_error);index++) - { - bytes[0]=Main_palette[index].R; - bytes[1]=Main_palette[index].G; - bytes[2]=Main_palette[index].B; - if (! Write_bytes(file,bytes,3)) - File_error=1; - } - } - - fclose(file); - - if (File_error) - remove(filename); - } - else - File_error=1; -} - - - - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// SCx //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -#pragma pack(1) -typedef struct -{ - byte Filler1[4]; - word Width; - word Height; - byte Filler2; - byte Planes; -} T_SCx_Header; -#pragma pack() - -// -- Tester si un fichier est au format SCx -------------------------------- -void Test_SCx(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - //byte Signature[3]; - T_SCx_Header SCx_header; - - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Lecture et vérification de la signature - if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header)))) - { - if ( (!memcmp(SCx_header.Filler1,"RIX",3)) - && SCx_header.Width && SCx_header.Height) - File_error=0; - } - // Fermeture du fichier - fclose(file); - } -} - - -// -- Lire un fichier au format SCx ----------------------------------------- -void Load_SCx(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - word x_pos,y_pos; - long size,real_size; - long file_size; - T_SCx_Header SCx_header; - T_Palette SCx_Palette; - - Get_full_filename(filename,0); - - File_error=0; - - if ((file=fopen(filename, "rb"))) - { - file_size=File_length_file(file); - - if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header)))) - { - Init_preview(SCx_header.Width,SCx_header.Height,file_size,FORMAT_SCx,PIXEL_SIMPLE); - if (File_error==0) - { - if (!SCx_header.Planes) - size=sizeof(T_Palette); - else - size=sizeof(T_Components)*(1<>3)*SCx_header.Planes; - real_size=(size/SCx_header.Planes)<<3; - LBM_buffer=(byte *)malloc(size); - HBPm1=SCx_header.Planes-1; - Image_HAM=0; - - for (y_pos=0;(y_pos>=1; - } -} - -//// CODAGE d'une partie d'IMAGE //// - -void PI1_16p_to_8b(byte * src,byte * dest) -{ - int i; // index du pixel à calculer - word byte_mask; // Masque de codage - word w0,w1,w2,w3; // Les 4 words bien ordonnés de la destination - - byte_mask=0x8000; - w0=w1=w2=w3=0; - for (i=0;i<16;i++) - { - // Pour coder le pixel n°i, il faut modifier les 4 words sur leur bit - // correspondant à celui du masque - - w0|=(src[i] & 0x01)?byte_mask:0x00; - w1|=(src[i] & 0x02)?byte_mask:0x00; - w2|=(src[i] & 0x04)?byte_mask:0x00; - w3|=(src[i] & 0x08)?byte_mask:0x00; - byte_mask>>=1; - } - dest[0]=w0 >> 8; - dest[1]=w0 & 0x00FF; - dest[2]=w1 >> 8; - dest[3]=w1 & 0x00FF; - dest[4]=w2 >> 8; - dest[5]=w2 & 0x00FF; - dest[6]=w3 >> 8; - dest[7]=w3 & 0x00FF; -} - -//// DECODAGE de la PALETTE //// - -void PI1_decode_palette(byte * src,byte * palette) -{ - int i; // Numéro de la couleur traitée - int ip; // index dans la palette - word w; // Word contenant le code - - // Schéma d'un word = - // - // Low High - // VVVV RRRR | 0000 BBBB - // 0321 0321 | 0321 - - ip=0; - for (i=0;i<16;i++) - { - w=((word)src[(i*2)+1]<<8) | src[(i*2)+0]; - - // Traitement des couleurs rouge, verte et bleue: - palette[ip++]=(((w & 0x0007) << 1) | ((w & 0x0008) >> 3)) << 4; - palette[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4; - palette[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 4; - } -} - -//// CODAGE de la PALETTE //// - -void PI1_code_palette(byte * palette,byte * dest) -{ - int i; // Numéro de la couleur traitée - int ip; // index dans la palette - word w; // Word contenant le code - - // Schéma d'un word = - // - // Low High - // VVVV RRRR | 0000 BBBB - // 0321 0321 | 0321 - - ip=0; - for (i=0;i<16;i++) - { - // Traitement des couleurs rouge, verte et bleue: - w =(((word)(palette[ip]>>2) & 0x38) >> 3) | (((word)(palette[ip]>>2) & 0x04) << 1); ip++; - w|=(((word)(palette[ip]>>2) & 0x38) << 9) | (((word)(palette[ip]>>2) & 0x04) << 13); ip++; - w|=(((word)(palette[ip]>>2) & 0x38) << 5) | (((word)(palette[ip]>>2) & 0x04) << 9); ip++; - - dest[(i*2)+0]=w & 0x00FF; - dest[(i*2)+1]=(w>>8); - } -} - - -// -- Tester si un fichier est au format PI1 -------------------------------- -void Test_PI1(void) -{ - FILE * file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - int size; // Taille du fichier - word resolution; // Résolution de l'image - - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Vérification de la taille - size=File_length_file(file); - if ((size==32034) || (size==32066)) - { - // Lecture et vérification de la résolution - if (Read_word_le(file,&resolution)) - { - if (resolution==0x0000) - File_error=0; - } - } - // Fermeture du fichier - fclose(file); - } -} - - -// -- Lire un fichier au format PI1 ----------------------------------------- -void Load_PI1(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - word x_pos,y_pos; - byte * buffer; - byte * ptr; - byte pixels[320]; - - Get_full_filename(filename,0); - - File_error=0; - if ((file=fopen(filename, "rb"))) - { - // allocation d'un buffer mémoire - buffer=(byte *)malloc(32034); - if (buffer!=NULL) - { - // Lecture du fichier dans le buffer - if (Read_bytes(file,buffer,32034)) - { - // Initialisation de la preview - Init_preview(320,200,File_length_file(file),FORMAT_PI1,PIXEL_SIMPLE); - if (File_error==0) - { - // Initialisation de la palette - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - PI1_decode_palette(buffer+2,(byte *)Main_palette); - Set_palette(Main_palette); - Remap_fileselector(); - - Main_image_width=320; - Main_image_height=200; - - // Chargement/décompression de l'image - ptr=buffer+34; - for (y_pos=0;y_pos<200;y_pos++) - { - for (x_pos=0;x_pos<(320>>4);x_pos++) - { - PI1_8b_to_16p(ptr,pixels+(x_pos<<4)); - ptr+=8; - } - for (x_pos=0;x_pos<320;x_pos++) - Pixel_load_function(x_pos,y_pos,pixels[x_pos]); - } - } - } - else - File_error=1; - free(buffer); - } - else - File_error=1; - fclose(file); - } - else - File_error=1; -} - - -// -- Sauver un fichier au format PI1 --------------------------------------- -void Save_PI1(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - short x_pos,y_pos; - byte * buffer; - byte * ptr; - byte pixels[320]; - - Get_full_filename(filename,0); - - File_error=0; - // Ouverture du fichier - if ((file=fopen(filename,"wb"))) - { - // allocation d'un buffer mémoire - buffer=(byte *)malloc(32066); - // Codage de la résolution - buffer[0]=0x00; - buffer[1]=0x00; - // Codage de la palette - PI1_code_palette((byte *)Main_palette,buffer+2); - // Codage de l'image - ptr=buffer+34; - for (y_pos=0;y_pos<200;y_pos++) - { - // Codage de la ligne - memset(pixels,0,320); - if (y_pos>4);x_pos++) - { - PI1_16p_to_8b(pixels+(x_pos<<4),ptr); - ptr+=8; - } - } - - memset(buffer+32034,0,32); // 32 extra NULL bytes at the end of the file to make ST Deluxe Paint happy - - if (Write_bytes(file,buffer,32066)) - { - fclose(file); - } - else // Error d'écriture (disque plein ou protégé) - { - fclose(file); - remove(filename); - File_error=1; - } - // Libération du buffer mémoire - free(buffer); - } - else - { - fclose(file); - remove(filename); - File_error=1; - } -} - - - - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// PC1 //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - - -//// DECOMPRESSION d'un buffer selon la méthode PACKBITS //// - -void PC1_uncompress_packbits(byte * src,byte * dest) -{ - int is,id; // Les indices de parcour des buffers - int n; // Octet de contrôle - - for (is=id=0;id<32000;) - { - n=src[is++]; - - if (n & 0x80) - { - // Recopier src[is] -n+1 fois - n=257-n; - for (;(n>0) && (id<32000);n--) - dest[id++]=src[is]; - is++; - } - else - { - // Recopier n+1 octets littéralement - n=n+1; - for (;(n>0) && (id<32000);n--) - dest[id++]=src[is++]; - } - - // Contrôle des erreurs - if (n>0) - File_error=1; - } -} - -//// COMPRESSION d'un buffer selon la méthode PACKBITS //// - -void PC1_compress_packbits(byte * src,byte * dest,int source_size,int * dest_size) -{ - int is; // index dans la source - int id; // index dans la destination - int ir; // index de la répétition - int n; // Taille des séquences - int repet; // "Il y a répétition" - - for (is=id=0;is0;n--) - dest[id++]=src[is++]; - } - - // On code la partie sans répétitions - if (repet) - { - // On compte la quantité de fois qu'il faut répéter la valeur - for (ir+=3;ir>=1; - } - } -} - -//// CODAGE d'une partie d'IMAGE //// - -// Transformation d'1 ligne de pixels en 4 plans de bits - -void PC1_1line_to_4bp(byte * src,byte * dst0,byte * dst1,byte * dst2,byte * dst3) -{ - int i,j; // Compteurs - int ip; // index du pixel à calculer - byte byte_mask; // Masque de decodage - byte b0,b1,b2,b3; // Les 4 octets des plans bits sources - - ip=0; - // Pour chacun des 40 octets des plans de bits - for (i=0;i<40;i++) - { - // Pour chacun des 8 bits des octets - byte_mask=0x80; - b0=b1=b2=b3=0; - for (j=0;j<8;j++) - { - b0|=(src[ip] & 0x01)?byte_mask:0x00; - b1|=(src[ip] & 0x02)?byte_mask:0x00; - b2|=(src[ip] & 0x04)?byte_mask:0x00; - b3|=(src[ip] & 0x08)?byte_mask:0x00; - ip++; - byte_mask>>=1; - } - dst0[i]=b0; - dst1[i]=b1; - dst2[i]=b2; - dst3[i]=b3; - } -} - - -// -- Tester si un fichier est au format PC1 -------------------------------- -void Test_PC1(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - int size; // Taille du fichier - word resolution; // Résolution de l'image - - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Vérification de la taille - size=File_length_file(file); - if ((size<=32066)) - { - // Lecture et vérification de la résolution - if (Read_word_le(file,&resolution)) - { - if (resolution==0x0080) - File_error=0; - } - } - // Fermeture du fichier - fclose(file); - } -} - - -// -- Lire un fichier au format PC1 ----------------------------------------- -void Load_PC1(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - int size; - word x_pos,y_pos; - byte * buffercomp; - byte * bufferdecomp; - byte * ptr; - byte pixels[320]; - - Get_full_filename(filename,0); - - File_error=0; - if ((file=fopen(filename, "rb"))) - { - size=File_length_file(file); - // allocation des buffers mémoire - buffercomp=(byte *)malloc(size); - bufferdecomp=(byte *)malloc(32000); - if ( (buffercomp!=NULL) && (bufferdecomp!=NULL) ) - { - // Lecture du fichier dans le buffer - if (Read_bytes(file,buffercomp,size)) - { - // Initialisation de la preview - Init_preview(320,200,File_length_file(file),FORMAT_PC1,PIXEL_SIMPLE); - if (File_error==0) - { - // Initialisation de la palette - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - PI1_decode_palette(buffercomp+2,(byte *)Main_palette); - Set_palette(Main_palette); - Remap_fileselector(); - - Main_image_width=320; - Main_image_height=200; - - // Décompression du buffer - PC1_uncompress_packbits(buffercomp+34,bufferdecomp); - - // Décodage de l'image - ptr=bufferdecomp; - for (y_pos=0;y_pos<200;y_pos++) - { - // Décodage de la scanline - PC1_4bp_to_1line(ptr,ptr+40,ptr+80,ptr+120,pixels); - ptr+=160; - // Chargement de la ligne - for (x_pos=0;x_pos<320;x_pos++) - Pixel_load_function(x_pos,y_pos,pixels[x_pos]); - } - } - } - else - File_error=1; - free(bufferdecomp); - free(buffercomp); - } - else - { - File_error=1; - free(bufferdecomp); - free(buffercomp); - } - fclose(file); - } - else - File_error=1; -} - - -// -- Sauver un fichier au format PC1 --------------------------------------- -void Save_PC1(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - int size; - short x_pos,y_pos; - byte * buffercomp; - byte * bufferdecomp; - byte * ptr; - byte pixels[320]; - - Get_full_filename(filename,0); - - File_error=0; - // Ouverture du fichier - if ((file=fopen(filename,"wb"))) - { - // Allocation des buffers mémoire - bufferdecomp=(byte *)malloc(32000); - buffercomp =(byte *)malloc(64066); - // Codage de la résolution - buffercomp[0]=0x80; - buffercomp[1]=0x00; - // Codage de la palette - PI1_code_palette((byte *)Main_palette,buffercomp+2); - // Codage de l'image - ptr=bufferdecomp; - for (y_pos=0;y_pos<200;y_pos++) - { - // Codage de la ligne - memset(pixels,0,320); - if (y_pos>4);x_pos++) - { - PI1_8b_to_16p(ptr,pixels+(x_pos<<4)); - ptr+=8; - } - for (x_pos=0;x_pos<320;x_pos++) - Pixel_load_function(x_pos,y_pos,pixels[x_pos]); - } - } - } - else - File_error=1; - free(buffer); - } - else - File_error=1; - fclose(file); - } - else - File_error=1; -} - -void Save_NEO(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - short x_pos,y_pos; - byte * buffer; - byte * ptr; - byte pixels[320]; - - Get_full_filename(filename,0); - - File_error=0; - // Ouverture du fichier - if ((file=fopen(filename,"wb"))) - { - // allocation d'un buffer mémoire - buffer=(byte *)malloc(32128); - // Codage de la résolution - buffer[0]=0x00; - buffer[1]=0x00; - buffer[2]=0x00; - buffer[3]=0x00; - // Codage de la palette - PI1_code_palette((byte *)Main_palette,buffer+4); - // Codage de l'image - ptr=buffer+128; - for (y_pos=0;y_pos<200;y_pos++) - { - // Codage de la ligne - memset(pixels,0,320); - if (y_pos>4);x_pos++) - { - PI1_16p_to_8b(pixels+(x_pos<<4),ptr); - ptr+=8; - } - } - - if (Write_bytes(file,buffer,32128)) - { - fclose(file); - } - else // Error d'écriture (disque plein ou protégé) - { - fclose(file); - remove(filename); - File_error=1; - } - // Libération du buffer mémoire - free(buffer); - } - else - { - fclose(file); - remove(filename); - File_error=1; - } -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// 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 1000: // screen or color - case 1002: // (screen or color) + loadaddr - 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 i; - byte background,hasLoadAddr=0; - int loadFormat=0; - enum c64_format {F_hires,F_multi,F_bitmap,F_screen,F_color}; - const char *c64_format_names[]={"hires","multicolor","bitmap","screen","color"}; - - // 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) - { - File_error=0; - file_size = File_length_file(file); - - switch (file_size) - { - case 1000: // screen or color - hasLoadAddr=0; - loadFormat=F_screen; - break; - - case 1002: // (screen or color) + loadaddr - hasLoadAddr=1; - loadFormat=F_screen; - break; - - case 8000: // raw bitmap - hasLoadAddr=0; - loadFormat=F_bitmap; - - case 8002: // raw bitmap with loadaddr - hasLoadAddr=1; - loadFormat=F_bitmap; - break; - - case 9000: // bitmap + screen - hasLoadAddr=0; - loadFormat=F_hires; - break; - - case 9002: // bitmap + screen + loadaddr - hasLoadAddr=1; - loadFormat=F_hires; - break; - - case 10001: // multicolor - hasLoadAddr=0; - loadFormat=F_multi; - break; - - case 10003: // multicolor + loadaddr - hasLoadAddr=1; - loadFormat=F_multi; - break; - - default: // then we don't know what it is. - File_error = 1; - - } - - 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 - - if (file_size>9002) - width=160; - - if (hasLoadAddr) - { - // get load address - Read_byte(file,&background); - Read_byte(file,&background); - sprintf(filename,"load at $%02x00",background); - } - else - { - sprintf(filename,"no addr"); - } - - if(file_size>9002) - { - Ratio_of_loaded_image = PIXEL_WIDE; - } - sprintf(Main_comment,"C64 %s, %s", - c64_format_names[loadFormat],filename); - Init_preview(width, height, file_size, FORMAT_C64, Ratio_of_loaded_image); // 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); - else - { - for(i=0;i<1000;i++) - { - colors[i]=1; - } - } - - if(width==160) - { - Read_bytes(file,nybble,1000); - Read_byte(file,&background); - Load_C64_multi(bitmap,colors,nybble,background); - } - else - { - Load_C64_hires(bitmap,colors); - } - - File_error = 0; - fclose(file); - } - else - File_error = 1; -} - -int Save_C64_window(byte *saveWhat, byte *loadAddr) -{ - int button; - unsigned int i; - T_Dropdown_button *what, *addr; - char * what_label[] = { - "All", - "Bitmap", - "Screen", - "Color" - }; - char * address_label[] = { - "None", - "$2000", - "$4000", - "$6000", - "$8000", - "$A000", - "$C000", - "$E000" - }; - - Open_window(200,120,"c64 settings"); - Window_set_normal_button(110,100,80,15,"Save",1,1,SDLK_RETURN); - Window_set_normal_button(10,100,80,15,"Cancel",1,1,SDLK_ESCAPE); - - Print_in_window(13,18,"Data:",MC_Dark,MC_Light); - what=Window_set_dropdown_button(10,28,90,15,70,what_label[*saveWhat],1, 0, 1, LEFT_SIDE); - Window_dropdown_clear_items(what); - for (i=0; i2) - { - 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; - } - bitmap[pos++]=bits; - //Write_byte(file,bits&255); - } - } - } - - file = fopen(filename,"wb"); - - if(!file) - { - Warning_message("File open failed"); - File_error = 1; - return 1; - } - - if (loadAddr) - { - Write_byte(file,0); - Write_byte(file,loadAddr); - } - if (saveWhat==0 || saveWhat==1) - Write_bytes(file,bitmap,8000); - if (saveWhat==0 || saveWhat==2) - Write_bytes(file,colors,1000); - - fclose(file); - return 0; -} - -int Save_C64_multi(char *filename, byte saveWhat, byte loadAddr) -{ - /* - 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,pos=0; - byte bitmap[8000],screen[1000],nybble[1000]; - word numcolors,count; - dword cusage[256]; - byte i,background=0; - FILE *file; - - 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); - bitmap[pos++]=bits; - } - } - } - - file = fopen(filename,"wb"); - - if(!file) - { - Warning_message("File open failed"); - File_error = 1; - return 1; - } - - if (loadAddr) - { - Write_byte(file,0); - Write_byte(file,loadAddr); - } - - if (saveWhat==0 || saveWhat==1) - Write_bytes(file,bitmap,8000); - - if (saveWhat==0 || saveWhat==2) - Write_bytes(file,screen,1000); - - if (saveWhat==0 || saveWhat==3) - Write_bytes(file,nybble,1000); - - if (saveWhat==0) - Write_byte(file,background); - - fclose(file); - //printf("\nbg:%d\n",background); - return 0; -} - -void Save_C64(void) -{ - char filename[MAX_PATH_CHARACTERS]; - static byte saveWhat=0, loadAddr=0; - dword numcolors,cusage[256]; - numcolors=Count_used_colors(cusage); - - Get_full_filename(filename,0); - - 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; - } - - if(!Save_C64_window(&saveWhat,&loadAddr)) - { - File_error = 1; - return; - } - //printf("saveWhat=%d, loadAddr=%d\n",saveWhat,loadAddr); - - if (Main_image_width==320) - File_error = Save_C64_hires(filename,saveWhat,loadAddr); - else - File_error = Save_C64_multi(filename,saveWhat,loadAddr); -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// PNG //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -#ifndef __no_pnglib__ - -// -- Tester si un fichier est au format PNG -------------------------------- -void Test_PNG(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - byte png_header[8]; - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Lecture du header du fichier - if (Read_bytes(file,png_header,8)) - { - if ( !png_sig_cmp(png_header, 0, 8)) - File_error=0; - } - fclose(file); - } -} - -png_bytep * Row_pointers; -// -- Lire un fichier au format PNG ----------------------------------------- -void Load_PNG(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - byte png_header[8]; - byte row_pointers_allocated; - - png_structp png_ptr; - png_infop info_ptr; - - Get_full_filename(filename,0); - - File_error=0; - - if ((file=fopen(filename, "rb"))) - { - // Load header (8 first bytes) - if (Read_bytes(file,png_header,8)) - { - // Do we recognize a png file signature ? - if ( !png_sig_cmp(png_header, 0, 8)) - { - // Prepare internal PNG loader - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr) - { - // Prepare internal PNG loader - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr) - { - png_byte color_type; - png_byte bit_depth; - - // Setup a return point. If a pnglib loading error occurs - // in this if(), the else will be executed. - if (!setjmp(png_jmpbuf(png_ptr))) - { - png_init_io(png_ptr, file); - // Inform pnglib we already loaded the header. - png_set_sig_bytes(png_ptr, 8); - - // Load file information - png_read_info(png_ptr, info_ptr); - color_type = info_ptr->color_type; - bit_depth = info_ptr->bit_depth; - - // If it's any supported file - // (Note: As of writing this, this test covers every possible - // image format of libpng) - if (color_type == PNG_COLOR_TYPE_PALETTE - || color_type == PNG_COLOR_TYPE_GRAY - || color_type == PNG_COLOR_TYPE_GRAY_ALPHA - || color_type == PNG_COLOR_TYPE_RGB - || color_type == PNG_COLOR_TYPE_RGB_ALPHA - ) - { - int num_text; - png_text *text_ptr; - - int unit_type; - png_uint_32 res_x; - png_uint_32 res_y; - - // Comment (tEXt) - Main_comment[0]='\0'; // Clear the previous comment - if ((num_text=png_get_text(png_ptr, info_ptr, &text_ptr, NULL))) - { - while (num_text--) - { - if (!strcmp(text_ptr[num_text].key,"Title")) - { - int size; - size = Min(text_ptr[num_text].text_length, COMMENT_SIZE); - strncpy(Main_comment, text_ptr[num_text].text, size); - Main_comment[size]='\0'; - break; // Skip all others tEXt chunks - } - } - } - // Pixel Ratio (pHYs) - if (png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type)) - { - // Ignore unit, and use the X/Y ratio as a hint for - // WIDE or TALL pixels - if (res_x>0 && res_y>0) - { - if (res_y/res_x>1) - { - Ratio_of_loaded_image=PIXEL_WIDE; - } - else if (res_x/res_y>1) - { - Ratio_of_loaded_image=PIXEL_TALL; - } - } - } - if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) - Init_preview_24b(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG); - else - Init_preview(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG,Ratio_of_loaded_image); - - if (File_error==0) - { - int x,y; - png_colorp palette; - int num_palette; - - // 16-bit images - if (bit_depth == 16) - { - // Reduce to 8-bit - png_set_strip_16(png_ptr); - } - else if (bit_depth < 8) - { - // Inform libpng we want one byte per pixel, - // even though the file was less than 8bpp - png_set_packing(png_ptr); - } - - // Images with alpha channel - if (color_type & PNG_COLOR_MASK_ALPHA) - { - // Tell libpng to ignore it - png_set_strip_alpha(png_ptr); - } - - // Greyscale images : - if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - // Map low bpp greyscales to full 8bit (0-255 range) - if (bit_depth < 8) - png_set_gray_1_2_4_to_8(png_ptr); - - // Create greyscale palette - for (x=0;x<256;x++) - { - Main_palette[x].R=x; - Main_palette[x].G=x; - Main_palette[x].B=x; - } - } - else if (color_type == PNG_COLOR_TYPE_PALETTE) // Palette images - { - - if (bit_depth < 8) - { - // Clear unused colors - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - } - // Load the palette - png_get_PLTE(png_ptr, info_ptr, &palette, - &num_palette); - for (x=0;xwidth; - Main_image_height=info_ptr->height; - - png_set_interlace_handling(png_ptr); - png_read_update_info(png_ptr, info_ptr); - - // Allocate row pointers - Row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * Main_image_height); - row_pointers_allocated = 0; - - /* read file */ - if (!setjmp(png_jmpbuf(png_ptr))) - { - if (color_type == PNG_COLOR_TYPE_GRAY - || color_type == PNG_COLOR_TYPE_GRAY_ALPHA - || color_type == PNG_COLOR_TYPE_PALETTE - ) - { - // 8bpp - - for (y=0; yrowbytes); - row_pointers_allocated = 1; - - png_read_image(png_ptr, Row_pointers); - - for (y=0; yrowbytes); - row_pointers_allocated = 1; - - png_read_image(png_ptr, Row_pointers); - - for (y=0; y +*/ + +///@file miscfileformats.c +/// Formats that aren't fully saving, either because of palette restrictions or other things + +#include "global.h" +#include "limits.h" +#include "loadsave.h" +#include "struct.h" +#include "windows.h" + +//////////////////////////////////// PAL //////////////////////////////////// + +// -- Tester si un fichier est au format PAL -------------------------------- +void Test_PAL(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + long file_size; // Taille du fichier + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Lecture de la taille du fichier + file_size=File_length_file(file); + fclose(file); + // Le fichier ne peut être au format PAL que si sa taille vaut 768 octets + if (file_size==sizeof(T_Palette)) + File_error=0; + } +} + + +// -- Lire un fichier au format PAL ----------------------------------------- +void Load_PAL(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + //long file_size; // Taille du fichier + + + Get_full_filename(filename,0); + File_error=0; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + T_Palette palette_64; + // Init_preview(?); // Pas possible... pas d'image... + + // Lecture du fichier dans Main_palette + if (Read_bytes(file,palette_64,sizeof(T_Palette))) + { + Palette_64_to_256(palette_64); + memcpy(Main_palette,palette_64,sizeof(T_Palette)); + Set_palette(Main_palette); + Remap_fileselector(); + + // On dessine une preview de la palette (si chargement=preview) + Draw_palette_preview(); + } + else + File_error=2; + + // Fermeture du fichier + fclose(file); + } + else + // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur + File_error=1; +} + + +// -- Sauver un fichier au format PAL --------------------------------------- +void Save_PAL(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + //long file_size; // Taille du fichier + + Get_full_filename(filename,0); + + File_error=0; + + // Ouverture du fichier + if ((file=fopen(filename,"wb"))) + { + T_Palette palette_64; + memcpy(palette_64,Main_palette,sizeof(T_Palette)); + Palette_256_to_64(palette_64); + // Enregistrement de Main_palette dans le fichier + if (! Write_bytes(file,palette_64,sizeof(T_Palette))) + { + File_error=1; + fclose(file); + remove(filename); + } + else // Ecriture correcte => Fermeture normale du fichier + fclose(file); + } + else // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur + { + File_error=1; + fclose(file); + remove(filename); + // On se fout du résultat de l'opération car si ça + // renvoie 0 c'est que le fichier avait été partiel- + // -lement écrit, sinon pas du tout. Or dans tous les + // cas ça revient au même pour nous: Sauvegarde ratée! + } +} + + +//////////////////////////////////// PKM //////////////////////////////////// +#pragma pack(1) +typedef struct +{ + char Ident[3]; // Chaîne "PKM" } + byte Method; // Compression method + // 0 = compression en ligne (c)KM + // autres = inconnues pour le moment + byte recog1; // Octet de reconnaissance sur 1 octet } + byte recog2; // Octet de reconnaissance sur 2 octets } + word Width; // width de l'image + word Height; // height de l'image + T_Palette Palette; // Palette RVB 256*3 + word Jump; // Taille du saut entre le header et l'image: + // On va s'en servir pour rajouter un commentaire +} T_PKM_Header; +#pragma pack() + +// -- Tester si un fichier est au format PKM -------------------------------- +void Test_PKM(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + T_PKM_Header header; + + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Lecture du header du fichier + if (Read_bytes(file,&header,sizeof(T_PKM_Header))) + { + // On regarde s'il y a la signature PKM suivie de la méthode 0. + // La constante "PKM" étant un chaîne, elle se termine toujours par 0. + // Donc pas la peine de s'emm...er à regarder si la méthode est à 0. + if ( (!memcmp(&header,"PKM",4)) && header.Width && header.Height) + File_error=0; + } + fclose(file); + } +} + + +// -- Lire un fichier au format PKM ----------------------------------------- +void Load_PKM(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + T_PKM_Header header; + byte color; + byte temp_byte; + word len; + word index; + dword Compteur_de_pixels; + dword Compteur_de_donnees_packees; + dword image_size; + dword Taille_pack; + long file_size; + + Get_full_filename(filename,0); + + File_error=0; + + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + + if (Read_bytes(file,&header,sizeof(T_PKM_Header))) + { + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + header.Width = SDL_Swap16(header.Width); + header.Height = SDL_Swap16(header.Height); + header.Jump = SDL_Swap16(header.Jump); +#endif + + Main_comment[0]='\0'; // On efface le commentaire + if (header.Jump) + { + index=0; + while ( (indexCOMMENT_SIZE) + { + color=temp_byte; // On se sert de color comme + temp_byte=COMMENT_SIZE; // variable temporaire + color-=COMMENT_SIZE; + } + else + color=0; + + if (Read_bytes(file,Main_comment,temp_byte)) + { + index+=temp_byte; + Main_comment[temp_byte]='\0'; + if (color) + if (fseek(file,color,SEEK_CUR)) + File_error=2; + } + else + File_error=2; + } + else + File_error=2; + break; + + case 1 : // Dimensions de l'écran d'origine + if (Read_byte(file,&temp_byte)) + { + if (temp_byte==4) + { + index+=4; + if ( ! Read_word_le(file,(word *) &Original_screen_X) + || !Read_word_le(file,(word *) &Original_screen_Y) ) + File_error=2; + } + else + File_error=2; + } + else + File_error=2; + break; + + case 2 : // color de transparence + if (Read_byte(file,&temp_byte)) + { + if (temp_byte==1) + { + index++; + if (! Read_byte(file,&Back_color)) + File_error=2; + } + else + File_error=2; + } + else + File_error=2; + break; + + default: + if (Read_byte(file,&temp_byte)) + { + index+=temp_byte; + if (fseek(file,temp_byte,SEEK_CUR)) + File_error=2; + } + else + File_error=2; + } + } + else + File_error=2; + } + if ( (!File_error) && (index!=header.Jump) ) + File_error=2; + } + + /*Init_lecture();*/ + + if (!File_error) + { + Init_preview(header.Width,header.Height,file_size,FORMAT_PKM,PIXEL_SIMPLE); + if (File_error==0) + { + + Main_image_width=header.Width; + Main_image_height=header.Height; + image_size=(dword)(Main_image_width*Main_image_height); + // Palette lue en 64 + memcpy(Main_palette,header.Palette,sizeof(T_Palette)); + Palette_64_to_256(Main_palette); + Set_palette(Main_palette); + Remap_fileselector(); + + Compteur_de_donnees_packees=0; + Compteur_de_pixels=0; + Taille_pack=(file_size)-sizeof(T_PKM_Header)-header.Jump; + + // Boucle de décompression: + while ( (Compteur_de_pixels>8); + Write_one_byte(file,Screen_height&0xFF); + Write_one_byte(file,Screen_height>>8); + // Ecriture de la back-color + Write_one_byte(file,2); + Write_one_byte(file,1); + Write_one_byte(file,Back_color); + + // Routine de compression PKM de l'image + image_size=(dword)(Main_image_width*Main_image_height); + Compteur_de_pixels=0; + pixel_value=Read_pixel_function(0,0); + + while ( (Compteur_de_pixels=image_size) break; + pixel_value=Read_pixel_function(Compteur_de_pixels % Main_image_width,Compteur_de_pixels / Main_image_width); + } + + if ( (last_color!=header.recog1) && (last_color!=header.recog2) ) + { + if (repetitions==1) + Write_one_byte(file,last_color); + else + if (repetitions==2) + { + Write_one_byte(file,last_color); + Write_one_byte(file,last_color); + } + else + if ( (repetitions>2) && (repetitions<256) ) + { // RECON1/couleur/nombre + Write_one_byte(file,header.recog1); + Write_one_byte(file,last_color); + Write_one_byte(file,repetitions&0xFF); + } + else + if (repetitions>=256) + { // RECON2/couleur/hi(nombre)/lo(nombre) + Write_one_byte(file,header.recog2); + Write_one_byte(file,last_color); + Write_one_byte(file,repetitions>>8); + Write_one_byte(file,repetitions&0xFF); + } + } + else + { + if (repetitions<256) + { + Write_one_byte(file,header.recog1); + Write_one_byte(file,last_color); + Write_one_byte(file,repetitions&0xFF); + } + else + { + Write_one_byte(file,header.recog2); + Write_one_byte(file,last_color); + Write_one_byte(file,repetitions>>8); + Write_one_byte(file,repetitions&0xFF); + } + } + } + + End_write(file); + } + else + File_error=1; + fclose(file); + } + else + { + File_error=1; + fclose(file); + } + // S'il y a eu une erreur de sauvegarde, on ne va tout de même pas laisser + // ce fichier pourri traîner... Ca fait pas propre. + if (File_error) + remove(filename); +} + + +//////////////////////////////////// CEL //////////////////////////////////// +#pragma pack(1) +typedef struct +{ + word Width; // width de l'image + word Height; // height de l'image +} T_CEL_Header1; + +typedef struct +{ + byte Signature[4]; // Signature du format + byte Kind; // Type de fichier ($10=PALette $20=BitMaP) + byte Nb_bits; // Nombre de bits + word Filler1; // ??? + word Width; // width de l'image + word Height; // height de l'image + word X_offset; // Offset en X de l'image + word Y_offset; // Offset en Y de l'image + byte Filler2[16]; // ??? +} T_CEL_Header2; +#pragma pack() + +// -- Tester si un fichier est au format CEL -------------------------------- + +void Test_CEL(void) +{ + char filename[MAX_PATH_CHARACTERS]; + int size; + FILE *file; + T_CEL_Header1 header1; + T_CEL_Header2 header2; + int file_size; + + File_error=0; + Get_full_filename(filename,0); + file_size=File_length(filename); + if (file_size==0) + { + File_error = 1; // Si on ne peut pas faire de stat il vaut mieux laisser tomber + return; + } + + if (! (file=fopen(filename, "rb"))) + { + File_error = 1; + return; + } + if (Read_word_le(file,&header1.Width) && + Read_word_le(file,&header1.Height) ) + { + // Vu que ce header n'a pas de signature, il va falloir tester la + // cohérence de la dimension de l'image avec celle du fichier. + + size=file_size-sizeof(T_CEL_Header1); + if ( (!size) || ( (((header1.Width+1)>>1)*header1.Height)!=size ) ) + { + // Tentative de reconnaissance de la signature des nouveaux fichiers + + fseek(file,0,SEEK_SET); + if (Read_bytes(file,&header2.Signature,4) && + !memcmp(header2.Signature,"KiSS",4) && + Read_byte(file,&header2.Kind) && + (header2.Kind==0x20) && + Read_byte(file,&header2.Nb_bits) && + Read_word_le(file,&header2.Filler1) && + Read_word_le(file,&header2.Width) && + Read_word_le(file,&header2.Height) && + Read_word_le(file,&header2.X_offset) && + Read_word_le(file,&header2.Y_offset) && + Read_bytes(file,&header2.Filler2,16)) + { + // ok + } + else + File_error=1; + } + else + File_error=1; + } + else + { + File_error=1; + } + fclose(file); +} + + +// -- Lire un fichier au format CEL ----------------------------------------- + +void Load_CEL(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + T_CEL_Header1 header1; + T_CEL_Header2 header2; + short x_pos; + short y_pos; + byte last_byte=0; + long file_size; + + File_error=0; + Get_full_filename(filename,0); + if ((file=fopen(filename, "rb"))) + { + if (Read_bytes(file,&header1,sizeof(T_CEL_Header1))) + { + file_size=File_length_file(file); + if ( (file_size>(long int)sizeof(T_CEL_Header1)) + && ( (((header1.Width+1)>>1)*header1.Height)==(file_size-(long int)sizeof(T_CEL_Header1)) ) ) + { + // Chargement d'un fichier CEL sans signature (vieux fichiers) + Main_image_width=header1.Width; + Main_image_height=header1.Height; + Original_screen_X=Main_image_width; + Original_screen_Y=Main_image_height; + Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE); + if (File_error==0) + { + // Chargement de l'image + /*Init_lecture();*/ + for (y_pos=0;((y_pos> 4)); + } + else + Pixel_load_function(x_pos,y_pos,(last_byte & 15)); + /*Close_lecture();*/ + } + } + else + { + // On réessaye avec le nouveau format + + fseek(file,0,SEEK_SET); + if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) + { + // Chargement d'un fichier CEL avec signature (nouveaux fichiers) + + Main_image_width=header2.Width+header2.X_offset; + Main_image_height=header2.Height+header2.Y_offset; + Original_screen_X=Main_image_width; + Original_screen_Y=Main_image_height; + Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE); + if (File_error==0) + { + // Chargement de l'image + /*Init_lecture();*/ + + if (!File_error) + { + // Effacement du décalage + for (y_pos=0;y_pos> 4)); + } + else + Pixel_load_function(x_pos+header2.X_offset,y_pos+header2.Y_offset,(last_byte & 15)); + break; + + case 8: + for (y_pos=0;((y_pos16 sont utilisées dans l'image + for (x_pos=16;((x_pos<256) && (!Utilisation[x_pos]));x_pos++); + + if (x_pos==256) + { + // Cas d'une image 16 couleurs (écriture à l'ancien format) + + header1.Width =Main_image_width; + header1.Height=Main_image_height; + + if (Write_bytes(file,&header1,sizeof(T_CEL_Header1))) + { + // Sauvegarde de l'image + Init_write_buffer(); + for (y_pos=0;((y_pos>4)!=0) + File_error=1; + } + else + { + if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) + { + if (memcmp(header2.Signature,"KiSS",4)==0) + { + if (header2.Kind!=0x10) + File_error=1; + } + else + File_error=1; + } + else + File_error=1; + } + fclose(file); + } + else + File_error=1; +} + + +// -- Lire un fichier au format KCF ----------------------------------------- + +void Load_KCF(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + T_KCF_Header buffer; + T_CEL_Header2 header2; + byte bytes[3]; + int pal_index; + int color_index; + int index; + long file_size; + + + File_error=0; + Get_full_filename(filename,0); + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + if (file_size==sizeof(T_KCF_Header)) + { + // Fichier KCF à l'ancien format + + if (Read_bytes(file,&buffer,sizeof(T_KCF_Header))) + { + // Init_preview(?); // Pas possible... pas d'image... + + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + + // Chargement de la palette + for (pal_index=0;pal_index<10;pal_index++) + for (color_index=0;color_index<16;color_index++) + { + index=16+(pal_index*16)+color_index; + Main_palette[index].R=((buffer.Palette[pal_index].color[color_index].Byte1 >> 4) << 4); + Main_palette[index].B=((buffer.Palette[pal_index].color[color_index].Byte1 & 15) << 4); + Main_palette[index].G=((buffer.Palette[pal_index].color[color_index].Byte2 & 15) << 4); + } + + for (index=0;index<16;index++) + { + Main_palette[index].R=Main_palette[index+16].R; + Main_palette[index].G=Main_palette[index+16].G; + Main_palette[index].B=Main_palette[index+16].B; + } + + Set_palette(Main_palette); + Remap_fileselector(); + } + else + File_error=1; + } + else + { + // Fichier KCF au nouveau format + + if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) + { + // Init_preview(?); // Pas possible... pas d'image... + + index=(header2.Nb_bits==12)?16:0; + for (pal_index=0;pal_index> 4) << 4; + Main_palette[index].B=(bytes[0] & 15) << 4; + Main_palette[index].G=(bytes[1] & 15) << 4; + break; + + case 24: // RRRR RRRR | VVVV VVVV | BBBB BBBB + Read_bytes(file,bytes,3); + Main_palette[index].R=bytes[0]; + Main_palette[index].G=bytes[1]; + Main_palette[index].B=bytes[2]; + } + + index++; + } + } + + if (header2.Nb_bits==12) + for (index=0;index<16;index++) + { + Main_palette[index].R=Main_palette[index+16].R; + Main_palette[index].G=Main_palette[index+16].G; + Main_palette[index].B=Main_palette[index+16].B; + } + + Set_palette(Main_palette); + Remap_fileselector(); + } + else + File_error=1; + } + fclose(file); + } + else + File_error=1; + + if (!File_error) Draw_palette_preview(); +} + + +// -- Ecrire un fichier au format KCF --------------------------------------- + +void Save_KCF(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + T_KCF_Header buffer; + T_CEL_Header2 header2; + byte bytes[3]; + int pal_index; + int color_index; + int index; + dword Utilisation[256]; // Table d'utilisation de couleurs + + // On commence par compter l'utilisation de chaque couleurs + Count_used_colors(Utilisation); + + File_error=0; + Get_full_filename(filename,0); + if ((file=fopen(filename,"wb"))) + { + // Sauvegarde de la palette + + // On regarde si des couleurs >16 sont utilisées dans l'image + for (index=16;((index<256) && (!Utilisation[index]));index++); + + if (index==256) + { + // Cas d'une image 16 couleurs (écriture à l'ancien format) + + for (pal_index=0;pal_index<10;pal_index++) + for (color_index=0;color_index<16;color_index++) + { + index=16+(pal_index*16)+color_index; + buffer.Palette[pal_index].color[color_index].Byte1=((Main_palette[index].R>>4)<<4) | (Main_palette[index].B>>4); + buffer.Palette[pal_index].color[color_index].Byte2=Main_palette[index].G>>4; + } + + if (! Write_bytes(file,&buffer,sizeof(T_KCF_Header))) + File_error=1; + } + else + { + // Cas d'une image 256 couleurs (écriture au nouveau format) + + memcpy(header2.Signature,"KiSS",4); // Initialisation de la signature + header2.Kind=0x10; // Initialisation du type (PALette) + header2.Nb_bits=24; // Initialisation du nombre de bits + header2.Filler1=0; // Initialisation du filler 1 (?) + header2.Width=256; // Initialisation du nombre de couleurs + header2.Height=1; // Initialisation du nombre de palettes + header2.X_offset=0; // Initialisation du décalage X + header2.Y_offset=0; // Initialisation du décalage Y + for (index=0;index<16;index++) // Initialisation du filler 2 (?) + header2.Filler2[index]=0; + + if (! Write_bytes(file,&header2,sizeof(T_CEL_Header2))) + File_error=1; + + for (index=0;(index<256) && (!File_error);index++) + { + bytes[0]=Main_palette[index].R; + bytes[1]=Main_palette[index].G; + bytes[2]=Main_palette[index].B; + if (! Write_bytes(file,bytes,3)) + File_error=1; + } + } + + fclose(file); + + if (File_error) + remove(filename); + } + else + File_error=1; +} + + +//////////////////////////////////// PI1 //////////////////////////////////// + +//// DECODAGE d'une partie d'IMAGE //// + +void PI1_8b_to_16p(byte * src,byte * dest) +{ + int i; // index du pixel à calculer + word byte_mask; // Masque de decodage + word w0,w1,w2,w3; // Les 4 words bien ordonnés de la source + + byte_mask=0x8000; + w0=(((word)src[0])<<8) | src[1]; + w1=(((word)src[2])<<8) | src[3]; + w2=(((word)src[4])<<8) | src[5]; + w3=(((word)src[6])<<8) | src[7]; + for (i=0;i<16;i++) + { + // Pour décoder le pixel n°i, il faut traiter les 4 words sur leur bit + // correspondant à celui du masque + + dest[i]=((w0 & byte_mask)?0x01:0x00) | + ((w1 & byte_mask)?0x02:0x00) | + ((w2 & byte_mask)?0x04:0x00) | + ((w3 & byte_mask)?0x08:0x00); + byte_mask>>=1; + } +} + +//// CODAGE d'une partie d'IMAGE //// + +void PI1_16p_to_8b(byte * src,byte * dest) +{ + int i; // index du pixel à calculer + word byte_mask; // Masque de codage + word w0,w1,w2,w3; // Les 4 words bien ordonnés de la destination + + byte_mask=0x8000; + w0=w1=w2=w3=0; + for (i=0;i<16;i++) + { + // Pour coder le pixel n°i, il faut modifier les 4 words sur leur bit + // correspondant à celui du masque + + w0|=(src[i] & 0x01)?byte_mask:0x00; + w1|=(src[i] & 0x02)?byte_mask:0x00; + w2|=(src[i] & 0x04)?byte_mask:0x00; + w3|=(src[i] & 0x08)?byte_mask:0x00; + byte_mask>>=1; + } + dest[0]=w0 >> 8; + dest[1]=w0 & 0x00FF; + dest[2]=w1 >> 8; + dest[3]=w1 & 0x00FF; + dest[4]=w2 >> 8; + dest[5]=w2 & 0x00FF; + dest[6]=w3 >> 8; + dest[7]=w3 & 0x00FF; +} + +//// DECODAGE de la PALETTE //// + +void PI1_decode_palette(byte * src,byte * palette) +{ + int i; // Numéro de la couleur traitée + int ip; // index dans la palette + word w; // Word contenant le code + + // Schéma d'un word = + // + // Low High + // VVVV RRRR | 0000 BBBB + // 0321 0321 | 0321 + + ip=0; + for (i=0;i<16;i++) + { + w=((word)src[(i*2)+1]<<8) | src[(i*2)+0]; + + // Traitement des couleurs rouge, verte et bleue: + palette[ip++]=(((w & 0x0007) << 1) | ((w & 0x0008) >> 3)) << 4; + palette[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4; + palette[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 4; + } +} + +//// CODAGE de la PALETTE //// + +void PI1_code_palette(byte * palette,byte * dest) +{ + int i; // Numéro de la couleur traitée + int ip; // index dans la palette + word w; // Word contenant le code + + // Schéma d'un word = + // + // Low High + // VVVV RRRR | 0000 BBBB + // 0321 0321 | 0321 + + ip=0; + for (i=0;i<16;i++) + { + // Traitement des couleurs rouge, verte et bleue: + w =(((word)(palette[ip]>>2) & 0x38) >> 3) | (((word)(palette[ip]>>2) & 0x04) << 1); ip++; + w|=(((word)(palette[ip]>>2) & 0x38) << 9) | (((word)(palette[ip]>>2) & 0x04) << 13); ip++; + w|=(((word)(palette[ip]>>2) & 0x38) << 5) | (((word)(palette[ip]>>2) & 0x04) << 9); ip++; + + dest[(i*2)+0]=w & 0x00FF; + dest[(i*2)+1]=(w>>8); + } +} + + +// -- Tester si un fichier est au format PI1 -------------------------------- +void Test_PI1(void) +{ + FILE * file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + int size; // Taille du fichier + word resolution; // Résolution de l'image + + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Vérification de la taille + size=File_length_file(file); + if ((size==32034) || (size==32066)) + { + // Lecture et vérification de la résolution + if (Read_word_le(file,&resolution)) + { + if (resolution==0x0000) + File_error=0; + } + } + // Fermeture du fichier + fclose(file); + } +} + + +// -- Lire un fichier au format PI1 ----------------------------------------- +void Load_PI1(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + word x_pos,y_pos; + byte * buffer; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + if ((file=fopen(filename, "rb"))) + { + // allocation d'un buffer mémoire + buffer=(byte *)malloc(32034); + if (buffer!=NULL) + { + // Lecture du fichier dans le buffer + if (Read_bytes(file,buffer,32034)) + { + // Initialisation de la preview + Init_preview(320,200,File_length_file(file),FORMAT_PI1,PIXEL_SIMPLE); + if (File_error==0) + { + // Initialisation de la palette + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + PI1_decode_palette(buffer+2,(byte *)Main_palette); + Set_palette(Main_palette); + Remap_fileselector(); + + Main_image_width=320; + Main_image_height=200; + + // Chargement/décompression de l'image + ptr=buffer+34; + for (y_pos=0;y_pos<200;y_pos++) + { + for (x_pos=0;x_pos<(320>>4);x_pos++) + { + PI1_8b_to_16p(ptr,pixels+(x_pos<<4)); + ptr+=8; + } + for (x_pos=0;x_pos<320;x_pos++) + Pixel_load_function(x_pos,y_pos,pixels[x_pos]); + } + } + } + else + File_error=1; + free(buffer); + } + else + File_error=1; + fclose(file); + } + else + File_error=1; +} + + +// -- Sauver un fichier au format PI1 --------------------------------------- +void Save_PI1(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + short x_pos,y_pos; + byte * buffer; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + // Ouverture du fichier + if ((file=fopen(filename,"wb"))) + { + // allocation d'un buffer mémoire + buffer=(byte *)malloc(32066); + // Codage de la résolution + buffer[0]=0x00; + buffer[1]=0x00; + // Codage de la palette + PI1_code_palette((byte *)Main_palette,buffer+2); + // Codage de l'image + ptr=buffer+34; + for (y_pos=0;y_pos<200;y_pos++) + { + // Codage de la ligne + memset(pixels,0,320); + if (y_pos>4);x_pos++) + { + PI1_16p_to_8b(pixels+(x_pos<<4),ptr); + ptr+=8; + } + } + + memset(buffer+32034,0,32); // 32 extra NULL bytes at the end of the file to make ST Deluxe Paint happy + + if (Write_bytes(file,buffer,32066)) + { + fclose(file); + } + else // Error d'écriture (disque plein ou protégé) + { + fclose(file); + remove(filename); + File_error=1; + } + // Libération du buffer mémoire + free(buffer); + } + else + { + fclose(file); + remove(filename); + File_error=1; + } +} + + +//////////////////////////////////// PC1 //////////////////////////////////// + +//// DECOMPRESSION d'un buffer selon la méthode PACKBITS //// + +void PC1_uncompress_packbits(byte * src,byte * dest) +{ + int is,id; // Les indices de parcour des buffers + int n; // Octet de contrôle + + for (is=id=0;id<32000;) + { + n=src[is++]; + + if (n & 0x80) + { + // Recopier src[is] -n+1 fois + n=257-n; + for (;(n>0) && (id<32000);n--) + dest[id++]=src[is]; + is++; + } + else + { + // Recopier n+1 octets littéralement + n=n+1; + for (;(n>0) && (id<32000);n--) + dest[id++]=src[is++]; + } + + // Contrôle des erreurs + if (n>0) + File_error=1; + } +} + +//// COMPRESSION d'un buffer selon la méthode PACKBITS //// + +void PC1_compress_packbits(byte * src,byte * dest,int source_size,int * dest_size) +{ + int is; // index dans la source + int id; // index dans la destination + int ir; // index de la répétition + int n; // Taille des séquences + int repet; // "Il y a répétition" + + for (is=id=0;is0;n--) + dest[id++]=src[is++]; + } + + // On code la partie sans répétitions + if (repet) + { + // On compte la quantité de fois qu'il faut répéter la valeur + for (ir+=3;ir>=1; + } + } +} + +//// CODAGE d'une partie d'IMAGE //// + +// Transformation d'1 ligne de pixels en 4 plans de bits + +void PC1_1line_to_4bp(byte * src,byte * dst0,byte * dst1,byte * dst2,byte * dst3) +{ + int i,j; // Compteurs + int ip; // index du pixel à calculer + byte byte_mask; // Masque de decodage + byte b0,b1,b2,b3; // Les 4 octets des plans bits sources + + ip=0; + // Pour chacun des 40 octets des plans de bits + for (i=0;i<40;i++) + { + // Pour chacun des 8 bits des octets + byte_mask=0x80; + b0=b1=b2=b3=0; + for (j=0;j<8;j++) + { + b0|=(src[ip] & 0x01)?byte_mask:0x00; + b1|=(src[ip] & 0x02)?byte_mask:0x00; + b2|=(src[ip] & 0x04)?byte_mask:0x00; + b3|=(src[ip] & 0x08)?byte_mask:0x00; + ip++; + byte_mask>>=1; + } + dst0[i]=b0; + dst1[i]=b1; + dst2[i]=b2; + dst3[i]=b3; + } +} + + +// -- Tester si un fichier est au format PC1 -------------------------------- +void Test_PC1(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + int size; // Taille du fichier + word resolution; // Résolution de l'image + + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Vérification de la taille + size=File_length_file(file); + if ((size<=32066)) + { + // Lecture et vérification de la résolution + if (Read_word_le(file,&resolution)) + { + if (resolution==0x0080) + File_error=0; + } + } + // Fermeture du fichier + fclose(file); + } +} + + +// -- Lire un fichier au format PC1 ----------------------------------------- +void Load_PC1(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + int size; + word x_pos,y_pos; + byte * buffercomp; + byte * bufferdecomp; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + if ((file=fopen(filename, "rb"))) + { + size=File_length_file(file); + // allocation des buffers mémoire + buffercomp=(byte *)malloc(size); + bufferdecomp=(byte *)malloc(32000); + if ( (buffercomp!=NULL) && (bufferdecomp!=NULL) ) + { + // Lecture du fichier dans le buffer + if (Read_bytes(file,buffercomp,size)) + { + // Initialisation de la preview + Init_preview(320,200,File_length_file(file),FORMAT_PC1,PIXEL_SIMPLE); + if (File_error==0) + { + // Initialisation de la palette + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + PI1_decode_palette(buffercomp+2,(byte *)Main_palette); + Set_palette(Main_palette); + Remap_fileselector(); + + Main_image_width=320; + Main_image_height=200; + + // Décompression du buffer + PC1_uncompress_packbits(buffercomp+34,bufferdecomp); + + // Décodage de l'image + ptr=bufferdecomp; + for (y_pos=0;y_pos<200;y_pos++) + { + // Décodage de la scanline + PC1_4bp_to_1line(ptr,ptr+40,ptr+80,ptr+120,pixels); + ptr+=160; + // Chargement de la ligne + for (x_pos=0;x_pos<320;x_pos++) + Pixel_load_function(x_pos,y_pos,pixels[x_pos]); + } + } + } + else + File_error=1; + free(bufferdecomp); + free(buffercomp); + } + else + { + File_error=1; + free(bufferdecomp); + free(buffercomp); + } + fclose(file); + } + else + File_error=1; +} + + +// -- Sauver un fichier au format PC1 --------------------------------------- +void Save_PC1(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + int size; + short x_pos,y_pos; + byte * buffercomp; + byte * bufferdecomp; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + // Ouverture du fichier + if ((file=fopen(filename,"wb"))) + { + // Allocation des buffers mémoire + bufferdecomp=(byte *)malloc(32000); + buffercomp =(byte *)malloc(64066); + // Codage de la résolution + buffercomp[0]=0x80; + buffercomp[1]=0x00; + // Codage de la palette + PI1_code_palette((byte *)Main_palette,buffercomp+2); + // Codage de l'image + ptr=bufferdecomp; + for (y_pos=0;y_pos<200;y_pos++) + { + // Codage de la ligne + memset(pixels,0,320); + if (y_pos>4);x_pos++) + { + PI1_8b_to_16p(ptr,pixels+(x_pos<<4)); + ptr+=8; + } + for (x_pos=0;x_pos<320;x_pos++) + Pixel_load_function(x_pos,y_pos,pixels[x_pos]); + } + } + } + else + File_error=1; + free(buffer); + } + else + File_error=1; + fclose(file); + } + else + File_error=1; +} + +void Save_NEO(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + short x_pos,y_pos; + byte * buffer; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + // Ouverture du fichier + if ((file=fopen(filename,"wb"))) + { + // allocation d'un buffer mémoire + buffer=(byte *)malloc(32128); + // Codage de la résolution + buffer[0]=0x00; + buffer[1]=0x00; + buffer[2]=0x00; + buffer[3]=0x00; + // Codage de la palette + PI1_code_palette((byte *)Main_palette,buffer+4); + // Codage de l'image + ptr=buffer+128; + for (y_pos=0;y_pos<200;y_pos++) + { + // Codage de la ligne + memset(pixels,0,320); + if (y_pos>4);x_pos++) + { + PI1_16p_to_8b(pixels+(x_pos<<4),ptr); + ptr+=8; + } + } + + if (Write_bytes(file,buffer,32128)) + { + fclose(file); + } + else // Error d'écriture (disque plein ou protégé) + { + fclose(file); + remove(filename); + File_error=1; + } + // Libération du buffer mémoire + free(buffer); + } + else + { + fclose(file); + remove(filename); + File_error=1; + } +} + +//////////////////////////////////// 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 1000: // screen or color + case 1002: // (screen or color) + loadaddr + 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 i; + byte background,hasLoadAddr=0; + int loadFormat=0; + enum c64_format {F_hires,F_multi,F_bitmap,F_screen,F_color}; + const char *c64_format_names[]={"hires","multicolor","bitmap","screen","color"}; + + // 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) + { + File_error=0; + file_size = File_length_file(file); + + switch (file_size) + { + case 1000: // screen or color + hasLoadAddr=0; + loadFormat=F_screen; + break; + + case 1002: // (screen or color) + loadaddr + hasLoadAddr=1; + loadFormat=F_screen; + break; + + case 8000: // raw bitmap + hasLoadAddr=0; + loadFormat=F_bitmap; + + case 8002: // raw bitmap with loadaddr + hasLoadAddr=1; + loadFormat=F_bitmap; + break; + + case 9000: // bitmap + screen + hasLoadAddr=0; + loadFormat=F_hires; + break; + + case 9002: // bitmap + screen + loadaddr + hasLoadAddr=1; + loadFormat=F_hires; + break; + + case 10001: // multicolor + hasLoadAddr=0; + loadFormat=F_multi; + break; + + case 10003: // multicolor + loadaddr + hasLoadAddr=1; + loadFormat=F_multi; + break; + + default: // then we don't know what it is. + File_error = 1; + + } + + 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 + + if (file_size>9002) + width=160; + + if (hasLoadAddr) + { + // get load address + Read_byte(file,&background); + Read_byte(file,&background); + sprintf(filename,"load at $%02x00",background); + } + else + { + sprintf(filename,"no addr"); + } + + if(file_size>9002) + { + Ratio_of_loaded_image = PIXEL_WIDE; + } + sprintf(Main_comment,"C64 %s, %s", + c64_format_names[loadFormat],filename); + Init_preview(width, height, file_size, FORMAT_C64, Ratio_of_loaded_image); // 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); + else + { + for(i=0;i<1000;i++) + { + colors[i]=1; + } + } + + if(width==160) + { + Read_bytes(file,nybble,1000); + Read_byte(file,&background); + Load_C64_multi(bitmap,colors,nybble,background); + } + else + { + Load_C64_hires(bitmap,colors); + } + + File_error = 0; + fclose(file); + } + else + File_error = 1; +} + +int Save_C64_window(byte *saveWhat, byte *loadAddr) +{ + int button; + unsigned int i; + T_Dropdown_button *what, *addr; + char * what_label[] = { + "All", + "Bitmap", + "Screen", + "Color" + }; + char * address_label[] = { + "None", + "$2000", + "$4000", + "$6000", + "$8000", + "$A000", + "$C000", + "$E000" + }; + + Open_window(200,120,"c64 settings"); + Window_set_normal_button(110,100,80,15,"Save",1,1,SDLK_RETURN); + Window_set_normal_button(10,100,80,15,"Cancel",1,1,SDLK_ESCAPE); + + Print_in_window(13,18,"Data:",MC_Dark,MC_Light); + what=Window_set_dropdown_button(10,28,90,15,70,what_label[*saveWhat],1, 0, 1, LEFT_SIDE); + Window_dropdown_clear_items(what); + for (i=0; i2) + { + 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; + } + bitmap[pos++]=bits; + //Write_byte(file,bits&255); + } + } + } + + file = fopen(filename,"wb"); + + if(!file) + { + Warning_message("File open failed"); + File_error = 1; + return 1; + } + + if (loadAddr) + { + Write_byte(file,0); + Write_byte(file,loadAddr); + } + if (saveWhat==0 || saveWhat==1) + Write_bytes(file,bitmap,8000); + if (saveWhat==0 || saveWhat==2) + Write_bytes(file,colors,1000); + + fclose(file); + return 0; +} + +int Save_C64_multi(char *filename, byte saveWhat, byte loadAddr) +{ + /* + 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,pos=0; + byte bitmap[8000],screen[1000],nybble[1000]; + word numcolors,count; + dword cusage[256]; + byte i,background=0; + FILE *file; + + 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); + bitmap[pos++]=bits; + } + } + } + + file = fopen(filename,"wb"); + + if(!file) + { + Warning_message("File open failed"); + File_error = 1; + return 1; + } + + if (loadAddr) + { + Write_byte(file,0); + Write_byte(file,loadAddr); + } + + if (saveWhat==0 || saveWhat==1) + Write_bytes(file,bitmap,8000); + + if (saveWhat==0 || saveWhat==2) + Write_bytes(file,screen,1000); + + if (saveWhat==0 || saveWhat==3) + Write_bytes(file,nybble,1000); + + if (saveWhat==0) + Write_byte(file,background); + + fclose(file); + //printf("\nbg:%d\n",background); + return 0; +} + +void Save_C64(void) +{ + char filename[MAX_PATH_CHARACTERS]; + static byte saveWhat=0, loadAddr=0; + dword numcolors,cusage[256]; + numcolors=Count_used_colors(cusage); + + Get_full_filename(filename,0); + + 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; + } + + if(!Save_C64_window(&saveWhat,&loadAddr)) + { + File_error = 1; + return; + } + //printf("saveWhat=%d, loadAddr=%d\n",saveWhat,loadAddr); + + if (Main_image_width==320) + File_error = Save_C64_hires(filename,saveWhat,loadAddr); + else + File_error = Save_C64_multi(filename,saveWhat,loadAddr); +} + From 036d8008cbd23c949e93cde3799009cced3916c1 Mon Sep 17 00:00:00 2001 From: Yves Rizoud Date: Sat, 31 Oct 2009 15:46:07 +0000 Subject: [PATCH 26/30] (internal) Skins have their own GUI color indices : avoids sharing/restoring MC_ colors git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1121 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- buttons.c | 79 +++++++++++++++++++++++++------------------------------ init.c | 79 +++++++++++++++++++++++++------------------------------ main.c | 14 ++++++++++ palette.c | 6 ++--- struct.h | 12 ++++++++- windows.c | 10 +++---- 6 files changed, 105 insertions(+), 95 deletions(-) diff --git a/buttons.c b/buttons.c index bee902c2..6b1aba67 100644 --- a/buttons.c +++ b/buttons.c @@ -994,13 +994,6 @@ void Add_font_or_skin(const char *name) } -// declared in windows.c for remap -extern byte Old_black; -extern byte Old_dark; -extern byte Old_light; -extern byte Old_white; -extern byte Old_trans; - // Callback to display a skin name in the list void Draw_one_skin_name(word x, word y, word index, byte highlighted) { @@ -1009,8 +1002,7 @@ void Draw_one_skin_name(word x, word y, word index, byte highlighted) if (Skin_files_list.Nb_elements) { current_item = Get_item_by_index(&Skin_files_list, index); - // We use Old_ colors because previewing a skin mess up MC_ ... - Print_in_window(x,y,current_item->Short_name, Old_black, (highlighted)?Old_dark:Old_light); + Print_in_window(x,y,current_item->Short_name, MC_Black, (highlighted)?MC_Dark:MC_Light); } } @@ -1058,13 +1050,6 @@ void Button_Skins(void) selected_font = Find_file_in_fileselector(&Font_files_list, Config.Font_file); - // Do this before setting up the skin list because it will redraw itself using the old colors... - Old_black = MC_Black; - Old_dark = MC_Dark; - Old_light = MC_Light; - Old_white = MC_White; - Old_trans = MC_Trans; - // -------------------------------------------------------------- @@ -1119,7 +1104,7 @@ void Button_Skins(void) for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++) for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++) - Pixel_in_window(x, y, Gfx->preview[offs_y][x_pos]); + Pixel_in_window(x, y, Gfx->Preview[offs_y][x_pos]); Update_window_area(0, 0, Window_width, Window_height); @@ -1147,23 +1132,27 @@ void Button_Skins(void) if (gfx == NULL) // Error { Verbose_error_message(Gui_loading_error_message); + // Update preview + Window_rectangle(4, 14, 174, 16, MC_Light); } - - // Update preview - // The new palette is not in place but the skin is loaded using the - // new color indexes, so we have to reverse-remap it... - for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++) - for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++) - { - if (gfx->preview[offs_y][x_pos] == MC_Black) - Pixel_in_window(x, y, Old_black); - else if (gfx->preview[offs_y][x_pos] == MC_Dark) - Pixel_in_window(x, y, Old_dark); - else if (gfx->preview[offs_y][x_pos] == MC_Light) - Pixel_in_window(x, y, Old_light); - else if (gfx->preview[offs_y][x_pos] == MC_White) - Pixel_in_window(x, y, Old_white); - } + else + { + // Update preview + // The new palette is not in place but the skin is loaded using the + // new color indexes, so we have to reverse-remap it... + for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++) + for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++) + { + if (gfx->Preview[offs_y][x_pos] == gfx->Color_black) + Pixel_in_window(x, y, MC_Black); + else if (gfx->Preview[offs_y][x_pos] == gfx->Color_dark) + Pixel_in_window(x, y, MC_Dark); + else if (gfx->Preview[offs_y][x_pos] == gfx->Color_white) + Pixel_in_window(x, y, MC_White); + else if (gfx->Preview[offs_y][x_pos] == gfx->Color_light) + Pixel_in_window(x, y, MC_Light); + } + } Update_window_area(4, 14, 174, 16); break; @@ -1192,15 +1181,26 @@ void Button_Skins(void) if(clicked_button == 1) { - byte * new_font; + byte * new_font; - if (gfx != NULL) - { + if (gfx != NULL) + { free(Gfx); Gfx = gfx; free(Config.Skin_file); Config.Skin_file = strdup(skinsdir); + + Config.Fav_menu_colors[0] = gfx->Default_palette[gfx->Color_black]; + Config.Fav_menu_colors[1] = gfx->Default_palette[gfx->Color_dark]; + Config.Fav_menu_colors[2] = gfx->Default_palette[gfx->Color_light]; + Config.Fav_menu_colors[3] = gfx->Default_palette[gfx->Color_white]; + + MC_Black = gfx->Color_black; + MC_Dark = gfx->Color_dark; + MC_Light = gfx->Color_light; + MC_White = gfx->Color_white; + MC_Trans = gfx->Color_trans; } // (Re-)load the selected font new_font = Load_font(Get_item_by_index(&Font_files_list,selected_font)->Full_name); @@ -1223,13 +1223,6 @@ void Button_Skins(void) // and remap the skin Compute_optimal_menu_colors(Main_palette); - } else { - // Get the initial colors back - MC_Black = Old_black; - MC_Dark = Old_dark; - MC_Light = Old_light; - MC_White = Old_white; - MC_Trans = Old_trans; } Close_window(); diff --git a/init.c b/init.c index db239326..da18a635 100644 --- a/init.c +++ b/init.c @@ -123,11 +123,11 @@ byte GUI_seek_right(SDL_Surface *gui, int *start_x, int start_y, byte neutral_co return 1; } -byte Read_GUI_block(SDL_Surface *gui, int start_x, int start_y, void *dest, int width, int height, char * section, int type) +byte Read_GUI_block(T_Gui_skin *gfx, SDL_Surface *gui, int start_x, int start_y, void *dest, int width, int height, char * section, int type) { // type: 0 = normal GUI element, only 4 colors allowed // type: 1 = mouse cursor, 4 colors allowed + transparent - // type: 2 = brush icon or sieve pattern (only MC_White and MC_Trans) + // type: 2 = brush icon or sieve pattern (only gui->Color_white and gui->Color_trans) // type: 3 = raw bitmap (splash screen) byte * dest_ptr=dest; @@ -147,28 +147,28 @@ byte Read_GUI_block(SDL_Surface *gui, int start_x, int start_y, void *dest, int for (x=start_x; xColor_black && color != gfx->Color_dark && color != gfx->Color_light && color != gfx->Color_white)) { sprintf(Gui_loading_error_message, "Error in skin file: Was looking at %d,%d for a %d*%d object (%s) but at %d,%d a pixel was found with color %d which isn't one of the GUI colors (which were detected as %d,%d,%d,%d.\n", - start_x, start_y, height, width, section, x, y, color, MC_Black, MC_Dark, MC_Light, MC_White); + start_x, start_y, height, width, section, x, y, color, gfx->Color_black, gfx->Color_dark, gfx->Color_light, gfx->Color_white); return 1; } - if (type==1 && (color != MC_Black && color != MC_Dark && color != MC_Light && color != MC_White && color != MC_Trans)) + if (type==1 && (color != gfx->Color_black && color != gfx->Color_dark && color != gfx->Color_light && color != gfx->Color_white && color != gfx->Color_trans)) { sprintf(Gui_loading_error_message, "Error in skin file: Was looking at %d,%d for a %d*%d object (%s) but at %d,%d a pixel was found with color %d which isn't one of the mouse colors (which were detected as %d,%d,%d,%d,%d.\n", - start_x, start_y, height, width, section, x, y, color, MC_Black, MC_Dark, MC_Light, MC_White, MC_Trans); + start_x, start_y, height, width, section, x, y, color, gfx->Color_black, gfx->Color_dark, gfx->Color_light, gfx->Color_white, gfx->Color_trans); return 1; } if (type==2) { - if (color != MC_White && color != MC_Trans) + if (color != gfx->Color_white && color != gfx->Color_trans) { sprintf(Gui_loading_error_message, "Error in skin file: Was looking at %d,%d for a %d*%d object (%s) but at %d,%d a pixel was found with color %d which isn't one of the brush colors (which were detected as %d on %d.\n", - start_x, start_y, height, width, section, x, y, color, MC_White, MC_Trans); + start_x, start_y, height, width, section, x, y, color, gfx->Color_white, gfx->Color_trans); return 1; } // Conversion en 0/1 pour les brosses monochromes internes - color = (color != MC_Trans); + color = (color != gfx->Color_trans); } *dest_ptr=color; dest_ptr++; @@ -177,12 +177,12 @@ byte Read_GUI_block(SDL_Surface *gui, int start_x, int start_y, void *dest, int return 0; } -byte Read_GUI_pattern(SDL_Surface *gui, int start_x, int start_y, word *dest, char * section) +byte Read_GUI_pattern(T_Gui_skin *gfx, SDL_Surface *gui, int start_x, int start_y, word *dest, char * section) { byte buffer[256]; int x,y; - if (Read_GUI_block(gui, start_x, start_y, buffer, 16, 16, section, 2)) + if (Read_GUI_block(gfx, gui, start_x, start_y, buffer, 16, 16, section, 2)) return 1; for (y=0; y<16; y++) @@ -209,7 +209,7 @@ void Center_GUI_cursor(T_Gui_skin *gfx, byte *cursor_buffer, int cursor_number) { for (y=0;y<29;y++) { - if (cursor_buffer[y*29+start_x]!=MC_Trans) + if (cursor_buffer[y*29+start_x]!=gfx->Color_trans) { found=1; break; @@ -224,7 +224,7 @@ void Center_GUI_cursor(T_Gui_skin *gfx, byte *cursor_buffer, int cursor_number) { for (x=0;x<29;x++) { - if (cursor_buffer[start_y*29+x]!=MC_Trans) + if (cursor_buffer[start_y*29+x]!=gfx->Color_trans) { found=1; break; @@ -271,8 +271,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) Get_SDL_Palette(SDLPal, gfx->Default_palette); // Carré "noir" - MC_Black = Get_SDL_pixel_8(gui,cursor_x,cursor_y); - Fav_menu_colors[0] = gfx->Default_palette[MC_Black]; + gfx->Color_black = Get_SDL_pixel_8(gui,cursor_x,cursor_y); do { if (++cursor_x>=gui->w) @@ -281,10 +280,9 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) return 1; } color=Get_SDL_pixel_8(gui,cursor_x,cursor_y); - } while(color==MC_Black); + } while(color==gfx->Color_black); // Carré "foncé" - MC_Dark=color; - Fav_menu_colors[1] = gfx->Default_palette[MC_Dark]; + gfx->Color_dark = color; do { if (++cursor_x>=gui->w) @@ -293,10 +291,9 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) return 1; } color=Get_SDL_pixel_8(gui,cursor_x,cursor_y); - } while(color==MC_Dark); + } while(color==gfx->Color_dark); // Carré "clair" - MC_Light=color; - Fav_menu_colors[2] = gfx->Default_palette[MC_Light]; + gfx->Color_light = color; do { if (++cursor_x>gui->w) @@ -305,10 +302,9 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) return 1; } color=Get_SDL_pixel_8(gui,cursor_x,cursor_y); - } while(color==MC_Light); + } while(color==gfx->Color_light); // Carré "blanc" - MC_White=color; - Fav_menu_colors[3] = gfx->Default_palette[MC_White]; + gfx->Color_white = color; do { if (++cursor_x>=gui->w) @@ -317,9 +313,9 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) return 1; } color=Get_SDL_pixel_8(gui,cursor_x,cursor_y); - } while(color==MC_White); + } while(color==gfx->Color_white); // Carré "transparent" - MC_Trans=color; + gfx->Color_trans=color; do { if (++cursor_x>=gui->w) @@ -328,14 +324,14 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) return 1; } color=Get_SDL_pixel_8(gui,cursor_x,cursor_y); - } while(color==MC_Trans); + } while(color==gfx->Color_trans); // Reste : couleur neutre neutral_color=color; cursor_x=0; cursor_y=1; - while ((color=Get_SDL_pixel_8(gui,cursor_x,cursor_y))==MC_Black) + while ((color=Get_SDL_pixel_8(gui,cursor_x,cursor_y))==gfx->Color_black) { cursor_y++; if (cursor_y>=gui->h) @@ -348,13 +344,13 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) // Menu if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "menu")) return 1; - if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->Menu_block, MENU_WIDTH, MENU_HEIGHT,"menu",0)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Menu_block, MENU_WIDTH, MENU_HEIGHT,"menu",0)) return 1; cursor_x += MENU_WIDTH; if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "logo")) return 1; - if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->preview, 173, 16, "logo", 0)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Preview, 173, 16, "logo", 0)) return 1; cursor_y+=MENU_HEIGHT; @@ -371,7 +367,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "effect sprite")) return 1; } - if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->Effect_sprite[i], MENU_SPRITE_WIDTH, MENU_SPRITE_HEIGHT, "effect sprite",0)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Effect_sprite[i], MENU_SPRITE_WIDTH, MENU_SPRITE_HEIGHT, "effect sprite",0)) return 1; cursor_x+=MENU_SPRITE_WIDTH; } @@ -390,7 +386,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "mouse cursor")) return 1; } - if (Read_GUI_block(gui, cursor_x, cursor_y, mouse_cursor_area, 29, 29, "mouse cursor",1)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, mouse_cursor_area, 29, 29, "mouse cursor",1)) return 1; Center_GUI_cursor(gfx, (byte *)mouse_cursor_area,i); cursor_x+=29; @@ -410,7 +406,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "menu sprite")) return 1; } - if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->Menu_sprite[i], MENU_SPRITE_WIDTH, MENU_SPRITE_HEIGHT, "menu sprite",1)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Menu_sprite[i], MENU_SPRITE_WIDTH, MENU_SPRITE_HEIGHT, "menu sprite",1)) return 1; cursor_x+=MENU_SPRITE_WIDTH; } @@ -432,7 +428,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "brush icon")) return 1; } - if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->Paintbrush_sprite[i], PAINTBRUSH_WIDTH, PAINTBRUSH_HEIGHT, "brush icon",2)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Paintbrush_sprite[i], PAINTBRUSH_WIDTH, PAINTBRUSH_HEIGHT, "brush icon",2)) return 1; cursor_x+=PAINTBRUSH_WIDTH; } @@ -451,7 +447,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "sprite drive")) return 1; } - if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->Icon_sprite[i], ICON_SPRITE_WIDTH, ICON_SPRITE_HEIGHT, "sprite drive",1)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Icon_sprite[i], ICON_SPRITE_WIDTH, ICON_SPRITE_HEIGHT, "sprite drive",1)) return 1; cursor_x+=ICON_SPRITE_WIDTH; } @@ -461,7 +457,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "logo menu")) return 1; - if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->Logo_grafx2, 231, 56, "logo menu",3)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Logo_grafx2, 231, 56, "logo menu",3)) return 1; cursor_y+=56; @@ -478,7 +474,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "sieve pattern")) return 1; } - if (Read_GUI_pattern(gui, cursor_x, cursor_y, gfx->Sieve_pattern[i],"sieve pattern")) + if (Read_GUI_pattern(gfx, gui, cursor_x, cursor_y, gfx->Sieve_pattern[i],"sieve pattern")) return 1; cursor_x+=16; } @@ -500,7 +496,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "help font (norm)")) return 1; } - if (Read_GUI_block(gui, cursor_x, cursor_y, &(gfx->Help_font_norm[i][0][0]), 6, 8, "help font (norm)",0)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, &(gfx->Help_font_norm[i][0][0]), 6, 8, "help font (norm)",0)) return 1; cursor_x+=6; } @@ -522,7 +518,7 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "help font (bold)")) return 1; } - if (Read_GUI_block(gui, cursor_x, cursor_y, &(gfx->Bold_font[i][0][0]), 6, 8, "help font (bold)",0)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, &(gfx->Bold_font[i][0][0]), 6, 8, "help font (bold)",0)) return 1; cursor_x+=6; } @@ -557,15 +553,12 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) else dest=&(gfx->Help_font_t1[char_1++][0][0]); - if (Read_GUI_block(gui, cursor_x, cursor_y, dest, 6, 8, "help font (title)",0)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, dest, 6, 8, "help font (title)",0)) return 1; cursor_x+=6; } cursor_y+=8; - Current_help_section=0; - Help_position=0; - gfx->Preset_paintbrush_width [ 0]= 1; gfx->Preset_paintbrush_height[ 0]= 1; gfx->Paintbrush_type [ 0]=PAINTBRUSH_SHAPE_SQUARE; diff --git a/main.c b/main.c index 34c76392..3ab7d50a 100644 --- a/main.c +++ b/main.c @@ -550,6 +550,9 @@ int Init_program(int argc,char * argv[]) Analyze_command_line(argc,argv); + Current_help_section=0; + Help_position=0; + // Load sprites, palette etc. strcpy(Gui_skin_file,Config.Skin_file); Gfx = Load_graphics(Gui_skin_file); @@ -562,6 +565,17 @@ int Init_program(int argc,char * argv[]) Error(ERROR_GUI_MISSING); } } + Config.Fav_menu_colors[0] = Gfx->Default_palette[Gfx->Color_black]; + Config.Fav_menu_colors[1] = Gfx->Default_palette[Gfx->Color_dark]; + Config.Fav_menu_colors[2] = Gfx->Default_palette[Gfx->Color_light]; + Config.Fav_menu_colors[3] = Gfx->Default_palette[Gfx->Color_white]; + + MC_Black = Gfx->Color_black; + MC_Dark = Gfx->Color_dark; + MC_Light = Gfx->Color_light; + MC_White = Gfx->Color_white; + MC_Trans = Gfx->Color_trans; + // Infos sur les trames (Sieve) Sieve_mode=0; Copy_preset_sieve(0); diff --git a/palette.c b/palette.c index b308b918..20750ac8 100644 --- a/palette.c +++ b/palette.c @@ -433,9 +433,9 @@ void Set_nice_menu_colors(dword * color_usage,int not_picture) rgb[index].R=Main_palette[color].R; rgb[index].G=Main_palette[color].G; rgb[index].B=Main_palette[color].B; - Main_palette[color].R=Fav_menu_colors[index].R; - Main_palette[color].G=Fav_menu_colors[index].G; - Main_palette[color].B=Fav_menu_colors[index].B; + Main_palette[color].R=Config.Fav_menu_colors[index].R; + Main_palette[color].G=Config.Fav_menu_colors[index].G; + Main_palette[color].B=Config.Fav_menu_colors[index].B; } // Maintenant qu'on a placé notre nouvelle palette, on va chercher quelles diff --git a/struct.h b/struct.h index 81502a07..9867b4dc 100644 --- a/struct.h +++ b/struct.h @@ -427,8 +427,18 @@ typedef struct T_Palette Default_palette; /// Preview for displaying in the skin dialog - byte preview[16][173]; + byte Preview[16][173]; + /// Black GUI color index in skin palette + byte Color_black; + /// Dark GUI color index in skin palette + byte Color_dark; + /// Light GUI color index in skin palette + byte Color_light; + /// White GUI color index in skin palette + byte Color_white; + /// Transparent GUI color index in skin file + byte Color_trans; } T_Gui_skin; diff --git a/windows.c b/windows.c index 9ed71284..3eeabb75 100644 --- a/windows.c +++ b/windows.c @@ -2554,12 +2554,12 @@ void Compute_optimal_menu_colors(T_Components * palette) // Recherche du noir Compute_4_best_colors_for_1_menu_color - (Fav_menu_colors[0].R, Fav_menu_colors[0].G, Fav_menu_colors[0].B,palette,table); + (Config.Fav_menu_colors[0].R, Config.Fav_menu_colors[0].G, Config.Fav_menu_colors[0].B,palette,table); MC_Black=table[0]; // Recherche du blanc Compute_4_best_colors_for_1_menu_color - (Fav_menu_colors[3].R, Fav_menu_colors[3].G, Fav_menu_colors[3].B,palette,table); + (Config.Fav_menu_colors[3].R, Config.Fav_menu_colors[3].G, Config.Fav_menu_colors[3].B,palette,table); if (MC_Black!=table[0]) MC_White=table[0]; else @@ -2567,7 +2567,7 @@ void Compute_optimal_menu_colors(T_Components * palette) // Recherche du gris clair Compute_4_best_colors_for_1_menu_color - (Fav_menu_colors[2].R, Fav_menu_colors[2].G, Fav_menu_colors[2].B,palette,table); + (Config.Fav_menu_colors[2].R, Config.Fav_menu_colors[2].G, Config.Fav_menu_colors[2].B,palette,table); if ( (MC_Black!=table[0]) && (MC_White!=table[0]) ) MC_Light=table[0]; else @@ -2580,7 +2580,7 @@ void Compute_optimal_menu_colors(T_Components * palette) // Recherche du gris foncé Compute_4_best_colors_for_1_menu_color - (Fav_menu_colors[1].R, Fav_menu_colors[1].G, Fav_menu_colors[1].B,palette,table); + (Config.Fav_menu_colors[1].R, Config.Fav_menu_colors[1].G, Config.Fav_menu_colors[1].B,palette,table); if ( (MC_Black!=table[0]) && (MC_White!=table[0]) && (MC_Light!=table[0]) ) MC_Dark=table[0]; else @@ -2678,7 +2678,7 @@ void Remap_menu_sprites() // Skin preview for (j = 0; j < 173; j++) for (i = 0; i < 16; i++) - Remap_pixel(&Gfx->preview[i][j]); + Remap_pixel(&Gfx->Preview[i][j]); } Clear_border(MC_Black); } From fb3404e2baf460fefe2df017829db155d966c6e1 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 31 Oct 2009 16:42:08 +0000 Subject: [PATCH 27/30] Partial patch to allow loading spare page from command line. It's not working yet but does not introduce regressions instead. Cleaned up version of patch proposed on the issue tracker. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1122 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- main.c | 64 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/main.c b/main.c index 3ab7d50a..efc43569 100644 --- a/main.c +++ b/main.c @@ -173,18 +173,18 @@ void Error_function(int error_code, const char *filename, int line_number, const } // --------------------- Analyse de la ligne de commande --------------------- -void Analyze_command_line(int argc,char * argv[]) +void Analyze_command_line(int argc, char * argv[]) { char *buffer ; int index; - File_in_command_line=0; - Resolution_in_command_line=0; + File_in_command_line = 0; + Resolution_in_command_line = 0; - Current_resolution=Config.Default_resolution; + Current_resolution = Config.Default_resolution; - for (index=1; index 1) { - // plusieurs noms de fichier en argument + // Il y a déjà 2 noms de fichiers et on vient d'en trouver un 3ème Error(ERROR_COMMAND_LINE); Display_syntax(); exit(0); } else if (File_exists(argv[index])) { - File_in_command_line=1; + File_in_command_line ++; + buffer = Realpath(argv[index], NULL); - // On récupère le chemin complet du paramètre - // Et on découpe ce chemin en répertoire(path) + fichier(.ext) - buffer=Realpath(argv[index],NULL); - Extract_path(Main_file_directory, buffer); - Extract_filename(Main_filename, buffer); - free(buffer); - chdir(Main_file_directory); + if (File_in_command_line == 1) + { + // Separate path from filename + Extract_path(Main_file_directory, buffer); + Extract_filename(Main_filename, buffer); + DEBUG(Main_filename, 0); + free(buffer); + } else { + Extract_path(Spare_file_directory, buffer); + Extract_filename(Spare_filename, buffer); + DEBUG(Spare_filename, 1); + free(buffer); + } } else { @@ -548,7 +555,7 @@ int Init_program(int argc,char * argv[]) if (temp) Error(temp); - Analyze_command_line(argc,argv); + Analyze_command_line(argc, argv); Current_help_section=0; Help_position=0; @@ -650,7 +657,7 @@ int Init_program(int argc,char * argv[]) // Brouillon_* et pas les infos contenues dans la page de brouillon // elle-même ne m'inspire pas confiance mais ça a l'air de marcher sans // poser de problèmes, alors... - if (File_in_command_line) + if (File_in_command_line == 1) { strcpy(Spare_file_directory,Spare_current_directory); strcpy(Spare_filename,"NO_NAME.GIF"); @@ -808,11 +815,20 @@ int main(int argc,char * argv[]) if (Config.Opening_message && (!File_in_command_line)) Button_Message_initial(); - if (File_in_command_line) + switch (File_in_command_line) { - Button_Reload(); - Resolution_in_command_line=0; - } + case 2: + Button_Reload(); + DEBUG(Main_filename, 0); + DEBUG(Spare_filename, 0); + Button_Page(); + // no break ! proceed with the other file now + case 1: + Button_Reload(); + Resolution_in_command_line = 0; + default: + break; + } } Main_handler(); From e7f34fefe4ebc63bdaa8e781a8dea89b46bd0ac8 Mon Sep 17 00:00:00 2001 From: Yves Rizoud Date: Sat, 31 Oct 2009 17:07:56 +0000 Subject: [PATCH 28/30] Skin preview previews gui colors git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1123 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- buttons.c | 264 ++++++++++++++++++++++++++++-------------------------- global.h | 3 - init.c | 25 ++++++ init.h | 3 +- main.c | 105 ++++++++-------------- misc.c | 2 +- 6 files changed, 200 insertions(+), 202 deletions(-) diff --git a/buttons.c b/buttons.c index 6b1aba67..1629d45d 100644 --- a/buttons.c +++ b/buttons.c @@ -309,10 +309,10 @@ void Button_Select_forecolor(void) // Check if it's a double-click if (time_click - time_previous < Config.Double_click_speed) { - // Open palette window - Button_Palette(); + // Open palette window + Button_Palette(); } - } + } else if (color!=-1) { Hide_cursor(); @@ -964,8 +964,8 @@ void Add_font_or_skin(const char *name) fname=name; namelength = strlen(fname); if (namelength>=10 && fname[0]!='_' && !strncasecmp(fname, "skin_", 5) - && (!strcasecmp(fname+namelength-4,".png") - || !strcasecmp(fname+namelength-4,".gif"))) + && (!strcasecmp(fname+namelength-4,".png") + || !strcasecmp(fname+namelength-4,".gif"))) { Add_element_to_list(&Skin_files_list, name, 0); @@ -976,8 +976,8 @@ void Add_font_or_skin(const char *name) strcpy(Skin_files_list.First->Full_name, fname); // Reformat the short name differently strcpy(Skin_files_list.First->Short_name, - Format_filename(Skin_files_list.First->Full_name, 0) - ); + Format_filename(Skin_files_list.First->Full_name, 0) + ); } else if (namelength>=10 && !strncasecmp(fname, "font_", 5) && (!strcasecmp(fname+namelength-4,".png"))) { @@ -1031,8 +1031,13 @@ void Button_Skins(void) char * cursors[] = { "Solid", "Transparent", "Thin" }; T_Gui_skin * gfx = NULL; + #define FILESEL_Y 34 + // Show preferred colors + Set_color(MC_Dark, Config.Fav_menu_colors[1].R, Config.Fav_menu_colors[1].G, Config.Fav_menu_colors[1].B); + Set_color(MC_Light, Config.Fav_menu_colors[2].R, Config.Fav_menu_colors[2].G, Config.Fav_menu_colors[2].B); + // --- Read the contents of skins/ directory ------------------ // Here we use the same data container as the fileselectors. @@ -1067,11 +1072,11 @@ void Button_Skins(void) // List of skins skin_list = Window_set_list_button( - // Fileselector - Window_set_special_button(8, FILESEL_Y + 1, 144, 80), // 2 + // Fileselector + Window_set_special_button(8, FILESEL_Y + 1, 144, 80), // 2 // Scroller for the fileselector (file_scroller = Window_set_scroller_button(155, FILESEL_Y - 1, 82, - Skin_files_list.Nb_elements, 10, 0)), // 3 + Skin_files_list.Nb_elements, 10, 0)), // 3 Draw_one_skin_name); // 4 skin_list->Cursor_position = Find_file_in_fileselector(&Skin_files_list, Config.Skin_file); @@ -1086,17 +1091,17 @@ void Button_Skins(void) // Dropdown list to choose cursor type cursor_dropdown = Window_set_dropdown_button(172, 69, 104, 11, 0, - cursors[selected_cursor], 1, 0, 1, RIGHT_SIDE|LEFT_SIDE); // 7 + cursors[selected_cursor], 1, 0, 1, RIGHT_SIDE|LEFT_SIDE); // 7 for (temp = 0; temp<3; temp++) Window_dropdown_add_item(cursor_dropdown, temp, cursors[temp]); Window_set_normal_button(172, 87, 14, 14, - (Config.Display_image_limits)?"X":" ", -1, 1, SDLK_LAST); // 8 + (Config.Display_image_limits)?"X":" ", -1, 1, SDLK_LAST); // 8 Print_in_window( 190, 85,"Draw picture", MC_Dark, MC_Light); Print_in_window( 190, 94,"limits", MC_Dark, MC_Light); Window_set_normal_button(172, 111, 14, 14, - (Config.Separate_colors)?"X":" ", -1, 1, SDLK_LAST); // 9 + (Config.Separate_colors)?"X":" ", -1, 1, SDLK_LAST); // 9 Print_in_window( 190, 109,"Separate", MC_Dark, MC_Light); Print_in_window( 190, 118,"colors", MC_Dark, MC_Light); @@ -1116,66 +1121,77 @@ void Button_Skins(void) switch(clicked_button) { - case 1 : // OK - break; - case 2 : // doesn't happen - break; - case 3 : // doesn't happen - break; - case 4 : // a file is selected + case 1 : // OK + break; + case 2 : // doesn't happen + break; + case 3 : // doesn't happen + break; + case 4 : // a file is selected - // (Re-)load GUI graphics from selected skins - strcpy(skinsdir, Get_item_by_index(&Skin_files_list, - skin_list->List_start + skin_list->Cursor_position)->Full_name); + // (Re-)load GUI graphics from selected skins + strcpy(skinsdir, Get_item_by_index(&Skin_files_list, + skin_list->List_start + skin_list->Cursor_position)->Full_name); - gfx = Load_graphics(skinsdir); - if (gfx == NULL) // Error - { - Verbose_error_message(Gui_loading_error_message); - // Update preview - Window_rectangle(4, 14, 174, 16, MC_Light); - } - else - { - // Update preview - // The new palette is not in place but the skin is loaded using the - // new color indexes, so we have to reverse-remap it... - for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++) - for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++) - { - if (gfx->Preview[offs_y][x_pos] == gfx->Color_black) - Pixel_in_window(x, y, MC_Black); - else if (gfx->Preview[offs_y][x_pos] == gfx->Color_dark) - Pixel_in_window(x, y, MC_Dark); - else if (gfx->Preview[offs_y][x_pos] == gfx->Color_white) - Pixel_in_window(x, y, MC_White); - else if (gfx->Preview[offs_y][x_pos] == gfx->Color_light) - Pixel_in_window(x, y, MC_Light); - } - } - Update_window_area(4, 14, 174, 16); + gfx = Load_graphics(skinsdir); + if (gfx == NULL) // Error + { + Verbose_error_message(Gui_loading_error_message); + // Update preview + Window_rectangle(4, 14, 174, 16, MC_Light); + } + else + { + // Update preview + + // Display the bitmap according to its own color indices + for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++) + for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++) + { + if (gfx->Preview[offs_y][x_pos] == gfx->Color_black) + Pixel_in_window(x, y, MC_Black); + else if (gfx->Preview[offs_y][x_pos] == gfx->Color_dark) + Pixel_in_window(x, y, MC_Dark); + else if (gfx->Preview[offs_y][x_pos] == gfx->Color_white) + Pixel_in_window(x, y, MC_White); + else if (gfx->Preview[offs_y][x_pos] == gfx->Color_light) + Pixel_in_window(x, y, MC_Light); + } + // Actualize current screen according to preferred GUI colors + Set_color( + MC_Dark, + gfx->Default_palette[gfx->Color_dark].R, + gfx->Default_palette[gfx->Color_dark].G, + gfx->Default_palette[gfx->Color_dark].B); + Set_color( + MC_Light, + gfx->Default_palette[gfx->Color_light].R, + gfx->Default_palette[gfx->Color_light].G, + gfx->Default_palette[gfx->Color_light].B); + } + Update_window_area(4, 14, 174, 16); - break; - case 5 : // Font dropdown - selected_font = Window_attribute2; // Get the index of the chosen font. - break; - // 6: Cancel - case 7 : // Cursor - selected_cursor = Window_attribute2; - break; - case 8: // Display limits - showlimits = !showlimits; - Hide_cursor(); - Print_in_window(175, 90, (showlimits)?"X":" ", MC_Black, MC_Light); - Display_cursor(); - break; - case 9: // Separate colors - separatecolors = !separatecolors; - Hide_cursor(); - Print_in_window(175, 114, (separatecolors)?"X":" ", MC_Black, MC_Light); - Display_cursor(); - break; - } + break; + case 5 : // Font dropdown + selected_font = Window_attribute2; // Get the index of the chosen font. + break; + // 6: Cancel + case 7 : // Cursor + selected_cursor = Window_attribute2; + break; + case 8: // Display limits + showlimits = !showlimits; + Hide_cursor(); + Print_in_window(175, 90, (showlimits)?"X":" ", MC_Black, MC_Light); + Display_cursor(); + break; + case 9: // Separate colors + separatecolors = !separatecolors; + Hide_cursor(); + Print_in_window(175, 114, (separatecolors)?"X":" ", MC_Black, MC_Light); + Display_cursor(); + break; + } } while ( (clicked_button!=1) && (clicked_button !=6) && (Key != SDLK_ESCAPE)); @@ -1185,48 +1201,38 @@ void Button_Skins(void) if (gfx != NULL) { - free(Gfx); - Gfx = gfx; - - free(Config.Skin_file); - Config.Skin_file = strdup(skinsdir); - - Config.Fav_menu_colors[0] = gfx->Default_palette[gfx->Color_black]; - Config.Fav_menu_colors[1] = gfx->Default_palette[gfx->Color_dark]; - Config.Fav_menu_colors[2] = gfx->Default_palette[gfx->Color_light]; - Config.Fav_menu_colors[3] = gfx->Default_palette[gfx->Color_white]; - - MC_Black = gfx->Color_black; - MC_Dark = gfx->Color_dark; - MC_Light = gfx->Color_light; - MC_White = gfx->Color_white; - MC_Trans = gfx->Color_trans; + Set_current_skin(skinsdir, gfx); + } + // (Re-)load the selected font + new_font = Load_font(Get_item_by_index(&Font_files_list,selected_font)->Full_name); + if (new_font) + { + const char * fname; + + free(Menu_font); + Menu_font = new_font; + fname = Get_item_by_index(&Font_files_list,selected_font)->Full_name; + free(Config.Font_file); + Config.Font_file = strdup(fname); } - // (Re-)load the selected font - new_font = Load_font(Get_item_by_index(&Font_files_list,selected_font)->Full_name); - if (new_font) - { - const char * fname; - - free(Menu_font); - Menu_font = new_font; - fname = Get_item_by_index(&Font_files_list,selected_font)->Full_name; - free(Config.Font_file); - Config.Font_file = strdup(fname); - } // Confirm the change of cursor shape - Config.Cursor = selected_cursor; - Config.Display_image_limits = showlimits; - Config.Separate_colors = separatecolors; + Config.Cursor = selected_cursor; + Config.Display_image_limits = showlimits; + Config.Separate_colors = separatecolors; - // Now find the best colors for the new skin in the current palette - // and remap the skin - Compute_optimal_menu_colors(Main_palette); + // Now find the best colors for the new skin in the current palette + // and remap the skin + Compute_optimal_menu_colors(Main_palette); } + else + { + Set_palette(Main_palette); + } Close_window(); Unselect_button(BUTTON_SETTINGS); + // Raffichage du menu pour que les inscriptions qui y figurent soient retracées avec la nouvelle fonte Display_menu(); Display_cursor(); @@ -1236,7 +1242,7 @@ void Button_Skins(void) //---------------------------- Changement de page ---------------------------- void Button_Page(void) { - byte factor_index; + byte factor_index; char Temp_buffer[256]; Hide_cursor(); @@ -1502,30 +1508,30 @@ void Display_modes_list(short list_start, short cursor_position) if(Video_mode[current_mode].Fullscreen == 0) memcpy(str+9," Window ",20); else - { + { memcpy(str+9," Fullscreen ",13); - if (Video_mode[current_mode].Width*3 == Video_mode[current_mode].Height*4) - ratio=" 4:3"; - else if (Video_mode[current_mode].Width*9 == Video_mode[current_mode].Height*16) - ratio=" 16:9"; - else if (Video_mode[current_mode].Width*10 == Video_mode[current_mode].Height*16) - ratio=" 16:10"; - else if (Video_mode[current_mode].Width*145 == Video_mode[current_mode].Height*192) - ratio="192:145"; - else if (Video_mode[current_mode].Width*2 == Video_mode[current_mode].Height*3) - ratio=" 3:2"; - else if (Video_mode[current_mode].Width*3 == Video_mode[current_mode].Height*5) - ratio=" 5:3"; - else if (Video_mode[current_mode].Width*4 == Video_mode[current_mode].Height*5) - ratio=" 5:4"; - else if (Video_mode[current_mode].Width*16 == Video_mode[current_mode].Height*25) - ratio=" 25:16"; - else - ratio=" "; - - strcpy(str+21,ratio); - } + if (Video_mode[current_mode].Width*3 == Video_mode[current_mode].Height*4) + ratio=" 4:3"; + else if (Video_mode[current_mode].Width*9 == Video_mode[current_mode].Height*16) + ratio=" 16:9"; + else if (Video_mode[current_mode].Width*10 == Video_mode[current_mode].Height*16) + ratio=" 16:10"; + else if (Video_mode[current_mode].Width*145 == Video_mode[current_mode].Height*192) + ratio="192:145"; + else if (Video_mode[current_mode].Width*2 == Video_mode[current_mode].Height*3) + ratio=" 3:2"; + else if (Video_mode[current_mode].Width*3 == Video_mode[current_mode].Height*5) + ratio=" 5:3"; + else if (Video_mode[current_mode].Width*4 == Video_mode[current_mode].Height*5) + ratio=" 5:4"; + else if (Video_mode[current_mode].Width*16 == Video_mode[current_mode].Height*25) + ratio=" 25:16"; + else + ratio=" "; + + strcpy(str+21,ratio); + } Print_in_window(38,y_pos,str,text_color,background_color); } @@ -2698,7 +2704,7 @@ void Load_picture(byte image) Brush_width=1; *Brush=Fore_color; - free(Smear_brush); + free(Smear_brush); Smear_brush=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE); Smear_brush_height=MAX_PAINTBRUSH_SIZE; Smear_brush_width=MAX_PAINTBRUSH_SIZE; @@ -5642,7 +5648,7 @@ void Button_Text() cursor_position = font_list->Cursor_position; free(new_brush); - new_brush = NULL; + new_brush = NULL; Close_window(); Unselect_button(BUTTON_TEXT); Display_cursor(); diff --git a/global.h b/global.h index b2eef28d..a7082cb7 100644 --- a/global.h +++ b/global.h @@ -71,9 +71,6 @@ GFX2_GLOBAL byte MC_Light; ///< Index of color to use as "light grey" in the GUI GFX2_GLOBAL byte MC_White; ///< Index of color to use as "white" in the GUI menus. GFX2_GLOBAL byte MC_Trans; ///< Index of color to use as "transparent" while loading the GUI file. -/// Favorite menu colors (RGB values). -GFX2_GLOBAL T_Components Fav_menu_colors[4]; - // Input state GFX2_GLOBAL word Mouse_X; ///< Current mouse cursor position. GFX2_GLOBAL word Mouse_Y; ///< Current mouse cursor position. diff --git a/init.c b/init.c index da18a635..00b9a423 100644 --- a/init.c +++ b/init.c @@ -2472,3 +2472,28 @@ void Init_brush_container(void) Brush_container[i].Brush = NULL; } } + +void Set_current_skin(const char *skinfile, T_Gui_skin *gfx) +{ + // Free previous one + free(Gfx); + + // Assign main skin pointer + Gfx = gfx; + + // Change config + free(Config.Skin_file); + Config.Skin_file = strdup(skinfile); + + Config.Fav_menu_colors[0] = gfx->Default_palette[gfx->Color_black]; + Config.Fav_menu_colors[1] = gfx->Default_palette[gfx->Color_dark]; + Config.Fav_menu_colors[2] = gfx->Default_palette[gfx->Color_light]; + Config.Fav_menu_colors[3] = gfx->Default_palette[gfx->Color_white]; + + // Reassign GUI color indices + MC_Black = gfx->Color_black; + MC_Dark = gfx->Color_dark; + MC_Light = gfx->Color_light; + MC_White = gfx->Color_white; + MC_Trans = gfx->Color_trans; +} diff --git a/init.h b/init.h index 79ee6412..4ef9eeb4 100644 --- a/init.h +++ b/init.h @@ -21,8 +21,9 @@ ///@file init.h /// Initialization (and some de-initialization) functions. ////////////////////////////////////////////////////////////////////////////// - + T_Gui_skin *Load_graphics(const char * skin_file); +void Set_current_skin(const char *skinfile, T_Gui_skin *gfx); void Init_buttons(void); void Init_operations(void); void Init_brush_container(void); diff --git a/main.c b/main.c index efc43569..ade4ba8e 100644 --- a/main.c +++ b/main.c @@ -75,9 +75,6 @@ extern DECLSPEC int SDLCALL SDL_putenv(const char *variable); #endif -// filename for the current GUI skin file. -static char Gui_skin_file[MAX_PATH_CHARACTERS]; - //--- Affichage de la syntaxe, et de la liste des modes vidéos disponibles --- void Display_syntax(void) { @@ -173,18 +170,18 @@ void Error_function(int error_code, const char *filename, int line_number, const } // --------------------- Analyse de la ligne de commande --------------------- -void Analyze_command_line(int argc, char * argv[]) +void Analyze_command_line(int argc,char * argv[]) { char *buffer ; int index; - File_in_command_line = 0; - Resolution_in_command_line = 0; + File_in_command_line=0; + Resolution_in_command_line=0; - Current_resolution = Config.Default_resolution; + Current_resolution=Config.Default_resolution; - for (index = 1; index 1) + if (File_in_command_line) { - // Il y a déjà 2 noms de fichiers et on vient d'en trouver un 3ème + // plusieurs noms de fichier en argument Error(ERROR_COMMAND_LINE); Display_syntax(); exit(0); } else if (File_exists(argv[index])) { - File_in_command_line ++; - buffer = Realpath(argv[index], NULL); + File_in_command_line=1; - if (File_in_command_line == 1) - { - // Separate path from filename - Extract_path(Main_file_directory, buffer); - Extract_filename(Main_filename, buffer); - DEBUG(Main_filename, 0); - free(buffer); - } else { - Extract_path(Spare_file_directory, buffer); - Extract_filename(Spare_filename, buffer); - DEBUG(Spare_filename, 1); - free(buffer); - } + // On récupère le chemin complet du paramètre + // Et on découpe ce chemin en répertoire(path) + fichier(.ext) + buffer=Realpath(argv[index],NULL); + Extract_path(Main_file_directory, buffer); + Extract_filename(Main_filename, buffer); + free(buffer); + chdir(Main_file_directory); } else { @@ -333,6 +323,7 @@ int Init_program(int argc,char * argv[]) int temp; int starting_videomode; char program_directory[MAX_PATH_CHARACTERS]; + T_Gui_skin *gfx; // On crée dès maintenant les descripteurs des listes de pages pour la page // principale et la page de brouillon afin que leurs champs ne soient pas @@ -555,48 +546,35 @@ int Init_program(int argc,char * argv[]) if (temp) Error(temp); - Analyze_command_line(argc, argv); + Analyze_command_line(argc,argv); Current_help_section=0; Help_position=0; // Load sprites, palette etc. - strcpy(Gui_skin_file,Config.Skin_file); - Gfx = Load_graphics(Gui_skin_file); - if (Gfx == NULL) + gfx = Load_graphics(Config.Skin_file); + if (gfx == NULL) { - Gfx = Load_graphics("skin_modern.png"); - if (Gfx == NULL) + gfx = Load_graphics("skin_modern.png"); + if (gfx == NULL) { printf("%s", Gui_loading_error_message); Error(ERROR_GUI_MISSING); } } - Config.Fav_menu_colors[0] = Gfx->Default_palette[Gfx->Color_black]; - Config.Fav_menu_colors[1] = Gfx->Default_palette[Gfx->Color_dark]; - Config.Fav_menu_colors[2] = Gfx->Default_palette[Gfx->Color_light]; - Config.Fav_menu_colors[3] = Gfx->Default_palette[Gfx->Color_white]; - - MC_Black = Gfx->Color_black; - MC_Dark = Gfx->Color_dark; - MC_Light = Gfx->Color_light; - MC_White = Gfx->Color_white; - MC_Trans = Gfx->Color_trans; - - // Infos sur les trames (Sieve) - Sieve_mode=0; - Copy_preset_sieve(0); - - // Transfert des valeurs du .INI qui ne changent pas dans des variables - // plus accessibles: - // Let's load the colors from the skin instead ! + Set_current_skin(Config.Skin_file, gfx); + Fore_color=MC_White; + Back_color=MC_Black; + // Override colors // Gfx->Default_palette[MC_Black]=Fav_menu_colors[0]=Config.Fav_menu_colors[0]; // Gfx->Default_palette[MC_Dark] =Fav_menu_colors[1]=Config.Fav_menu_colors[1]; // Gfx->Default_palette[MC_Light]=Fav_menu_colors[2]=Config.Fav_menu_colors[2]; // Gfx->Default_palette[MC_White]=Fav_menu_colors[3]=Config.Fav_menu_colors[3]; Compute_optimal_menu_colors(Gfx->Default_palette); - Fore_color=MC_White; - Back_color=MC_Black; + + // Infos sur les trames (Sieve) + Sieve_mode=0; + Copy_preset_sieve(0); // Font if (!(Menu_font=Load_font(Config.Font_file))) @@ -657,7 +635,7 @@ int Init_program(int argc,char * argv[]) // Brouillon_* et pas les infos contenues dans la page de brouillon // elle-même ne m'inspire pas confiance mais ça a l'air de marcher sans // poser de problèmes, alors... - if (File_in_command_line == 1) + if (File_in_command_line) { strcpy(Spare_file_directory,Spare_current_directory); strcpy(Spare_filename,"NO_NAME.GIF"); @@ -815,20 +793,11 @@ int main(int argc,char * argv[]) if (Config.Opening_message && (!File_in_command_line)) Button_Message_initial(); - switch (File_in_command_line) + if (File_in_command_line) { - case 2: - Button_Reload(); - DEBUG(Main_filename, 0); - DEBUG(Spare_filename, 0); - Button_Page(); - // no break ! proceed with the other file now - case 1: - Button_Reload(); - Resolution_in_command_line = 0; - default: - break; - } + Button_Reload(); + Resolution_in_command_line=0; + } } Main_handler(); diff --git a/misc.c b/misc.c index 3d2c4679..1bf58df3 100644 --- a/misc.c +++ b/misc.c @@ -159,7 +159,7 @@ void Set_color(byte color, byte red, byte green, byte blue) comp.r=red; comp.g=green; comp.b=blue; - SDL_SetPalette(Screen_SDL, SDL_LOGPAL, &comp, color, 1); + SDL_SetPalette(Screen_SDL, SDL_PHYSPAL | SDL_LOGPAL, &comp, color, 1); } void Wait_end_of_click(void) From b021a52fc3a0491d6cf2821226e82e4d7233e969 Mon Sep 17 00:00:00 2001 From: Yves Rizoud Date: Sat, 31 Oct 2009 17:16:48 +0000 Subject: [PATCH 29/30] Skins: Fix preview area after loading invalid file git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1124 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- buttons.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buttons.c b/buttons.c index 1629d45d..b34e5049 100644 --- a/buttons.c +++ b/buttons.c @@ -1138,7 +1138,7 @@ void Button_Skins(void) { Verbose_error_message(Gui_loading_error_message); // Update preview - Window_rectangle(4, 14, 174, 16, MC_Light); + Window_rectangle(6, 14, 173, 16, MC_Light); } else { @@ -1169,7 +1169,7 @@ void Button_Skins(void) gfx->Default_palette[gfx->Color_light].G, gfx->Default_palette[gfx->Color_light].B); } - Update_window_area(4, 14, 174, 16); + Update_window_area(6, 14, 173, 16); break; case 5 : // Font dropdown From ba36fa675f180929d0c5d189c9939a7f835b564d Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 31 Oct 2009 17:33:04 +0000 Subject: [PATCH 30/30] =?UTF-8?q?-Moved=20test=20script=20to=20"scripts"?= =?UTF-8?q?=20directory=20-Allow=20to=20add=20other=20scripts=20to=20this?= =?UTF-8?q?=20dir=20and=20run=20them=20too.=20--Cette=20ligne,=20et=20les?= =?UTF-8?q?=20suivantes=20ci-dessous,=20seront=20ignor=C3=A9es--?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A trunk/scripts A + trunk/scripts/test.lua D trunk/test.lua M trunk/buttons.c M trunk/factory.c git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1125 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- buttons.c | 21 +++++++------ factory.c | 58 ++++++++++++++++++++++++++++++++++-- test.lua => scripts/test.lua | 0 3 files changed, 67 insertions(+), 12 deletions(-) rename test.lua => scripts/test.lua (100%) diff --git a/buttons.c b/buttons.c index b34e5049..75e0eba6 100644 --- a/buttons.c +++ b/buttons.c @@ -961,13 +961,13 @@ void Add_font_or_skin(const char *name) if (fname) fname++; else - fname=name; + fname = name; namelength = strlen(fname); if (namelength>=10 && fname[0]!='_' && !strncasecmp(fname, "skin_", 5) - && (!strcasecmp(fname+namelength-4,".png") - || !strcasecmp(fname+namelength-4,".gif"))) + && (!strcasecmp(fname + namelength - 4,".png") + || !strcasecmp(fname + namelength - 4,".gif"))) { - Add_element_to_list(&Skin_files_list, name, 0); + Add_element_to_list(&Skin_files_list, name, 0); if (fname[0]=='\0') return; @@ -979,9 +979,10 @@ void Add_font_or_skin(const char *name) Format_filename(Skin_files_list.First->Full_name, 0) ); } - else if (namelength>=10 && !strncasecmp(fname, "font_", 5) && (!strcasecmp(fname+namelength-4,".png"))) + else if (namelength>=10 && !strncasecmp(fname, "font_", 5) + && (!strcasecmp(fname + namelength - 4, ".png"))) { - Add_element_to_list(&Font_files_list, name, 0); + Add_element_to_list(&Font_files_list, name, 0); if (fname[0]=='\0') return; @@ -989,7 +990,8 @@ void Add_font_or_skin(const char *name) // Remove directory from full name strcpy(Font_files_list.First->Full_name, fname); // Reformat the short name differently - strcpy(Font_files_list.First->Short_name,Format_font_filename(Font_files_list.First->Full_name)); + strcpy(Font_files_list.First->Short_name, + Format_font_filename(Font_files_list.First->Full_name)); } } @@ -1002,7 +1004,8 @@ void Draw_one_skin_name(word x, word y, word index, byte highlighted) if (Skin_files_list.Nb_elements) { current_item = Get_item_by_index(&Skin_files_list, index); - Print_in_window(x,y,current_item->Short_name, MC_Black, (highlighted)?MC_Dark:MC_Light); + Print_in_window(x, y, current_item->Short_name, MC_Black, + (highlighted)?MC_Dark:MC_Light); } } @@ -1026,7 +1029,7 @@ void Button_Skins(void) byte separatecolors = Config.Separate_colors; byte showlimits = Config.Display_image_limits; - word x,y, x_pos, offs_y; + word x, y, x_pos, offs_y; char * cursors[] = { "Solid", "Transparent", "Thin" }; T_Gui_skin * gfx = NULL; diff --git a/factory.c b/factory.c index e781fce7..103cb65c 100644 --- a/factory.c +++ b/factory.c @@ -26,8 +26,10 @@ #include "buttons.h" #include "engine.h" #include "errors.h" +#include "filesel.h" // Get_item_by_index #include "global.h" #include "graph.h" +#include "io.h" // find_last_slash #include "misc.h" #include "readline.h" #include "sdlscreen.h" @@ -113,21 +115,68 @@ int L_GetColor(lua_State* L) return 3; } -int L_BrushEnable(lua_State* L) +int L_BrushEnable(__attribute__((unused)) lua_State* L) { Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH); return 0; } +// Handlers for window internals +T_Fileselector Scripts_list; + +// Callback to display a skin name in the list +void Draw_script_name(word x, word y, word index, byte highlighted) +{ + T_Fileselector_item * current_item; + + DEBUG("draw",index); + if (Scripts_list.Nb_elements) + { + current_item = Get_item_by_index(&Scripts_list, index); + Print_in_window(x, y, current_item->Short_name, MC_Black, + (highlighted)?MC_Dark:MC_Light); + } +} + +// Add a skin to the list +void Add_script(const char *name) +{ + Add_element_to_list(&Scripts_list, Find_last_slash(name)+1, 0); +} + void Button_Brush_Factory(void) { short clicked_button; + T_List_button* scriptlist; + T_Scroller_button* scriptscroll; + char scriptdir[MAX_PATH_CHARACTERS]; - Open_window(154, 162, "Brush Factory"); + Open_window(175, 162, "Brush Factory"); + + // Here we use the same data container as the fileselectors. + // Reinitialize the list + Free_fileselector_list(&Scripts_list); + strcpy(scriptdir, Data_directory); + strcat(scriptdir, "scripts/"); + // Add each found file to the list + For_each_file(scriptdir, Add_script); + // Sort it + Sort_list_of_files(&Scripts_list); Window_set_normal_button(77, 141, 67, 14, "Cancel", 0, 1, KEY_ESC); // 1 Window_set_normal_button(10, 141, 67, 14, "Run", 0, 1, 0); // 2 + #define FILESEL_Y 18 + Window_display_frame_in(6, FILESEL_Y - 2, 148, 84); // File selector + scriptlist = Window_set_list_button( + // Fileselector + Window_set_special_button(8, FILESEL_Y + 1, 144, 80), // 3 + // Scroller for the fileselector + (scriptscroll = Window_set_scroller_button(154, FILESEL_Y - 1, 82, + Scripts_list.Nb_elements, 10, 0)), // 4 + Draw_script_name); // 5 + Window_redraw_list(scriptlist); + Update_window_area(0, 0, Window_width, Window_height); Display_cursor(); @@ -161,7 +210,10 @@ void Button_Brush_Factory(void) // For debug only // luaL_openlibs(L); - if (luaL_loadfile(L,"./test.lua") != 0) + strcat(scriptdir, Get_item_by_index(&Scripts_list, + scriptlist->List_start + scriptlist->Cursor_position) + -> Full_name); + if (luaL_loadfile(L,scriptdir) != 0) Verbose_error_message(lua_tostring(L, 1)); else if (lua_pcall(L, 0, 0, 0) != 0) Verbose_error_message(lua_tostring(L, 1)); diff --git a/test.lua b/scripts/test.lua similarity index 100% rename from test.lua rename to scripts/test.lua