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/Makefile b/Makefile index 318f5256..cf0e13f3 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 @@ -227,8 +228,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 +254,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. @@ -262,16 +274,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 $(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 @@ -307,15 +315,36 @@ 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 : $(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 diff --git a/Makefile.dep b/Makefile.dep index 3f42c276..aaa84ec2 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -8,6 +8,10 @@ $(OBJDIR)/buttons.o: buttons.c const.h struct.h global.h misc.h graph.h engine.h $(OBJDIR)/engine.o: engine.c const.h struct.h global.h graph.h misc.h special.h \ buttons.h operatio.h shade.h errors.h sdlscreen.h windows.h brush.h \ input.h engine.h pages.h +$(OBJDIR)/factory.o: factory.c brush.h struct.h const.h buttons.h engine.h errors.h \ + filesel.h global.h graph.h io.h misc.h readline.h sdlscreen.h windows.h +$(OBJDIR)/fileformats.o: fileformats.c errors.h global.h struct.h const.h \ + loadsave.h misc.h $(OBJDIR)/filesel.o: filesel.c const.h struct.h global.h misc.h errors.h io.h \ windows.h sdlscreen.h loadsave.h mountlist.h engine.h readline.h \ input.h help.h filesel.h @@ -18,9 +22,10 @@ $(OBJDIR)/help.o: help.c const.h struct.h global.h misc.h engine.h helpfile.h \ help.h sdlscreen.h text.h keyboard.h windows.h input.h hotkeys.h \ errors.h pages.h $(OBJDIR)/hotkeys.o: hotkeys.c struct.h const.h global.h hotkeys.h -$(OBJDIR)/init.o: init.c const.h struct.h global.h graph.h buttons.h palette.h \ - help.h operatio.h misc.h errors.h keyboard.h io.h hotkeys.h setup.h \ - windows.h sdlscreen.h mountlist.h loadsave.h init.h transform.h +$(OBJDIR)/init.o: init.c buttons.h struct.h const.h errors.h global.h graph.h \ + init.h io.h factory.h help.h hotkeys.h keyboard.h loadsave.h misc.h \ + mountlist.h operatio.h palette.h sdlscreen.h setup.h transform.h \ + windows.h $(OBJDIR)/input.o: input.c global.h struct.h const.h keyboard.h sdlscreen.h \ windows.h errors.h misc.h input.h $(OBJDIR)/io.o: io.c struct.h const.h io.h realpath.h @@ -33,6 +38,8 @@ $(OBJDIR)/main.o: main.c const.h struct.h global.h graph.h misc.h init.h buttons io.h text.h setup.h windows.h brush.h palette.h realpath.h $(OBJDIR)/misc.o: misc.c struct.h const.h sdlscreen.h global.h errors.h buttons.h \ engine.h misc.h keyboard.h windows.h palette.h input.h +$(OBJDIR)/miscfileformats.o: miscfileformats.c global.h struct.h const.h loadsave.h \ + windows.h $(OBJDIR)/mountlist.o: mountlist.c $(OBJDIR)/op_c.o: op_c.c op_c.h struct.h const.h errors.h $(OBJDIR)/operatio.o: operatio.c const.h struct.h global.h misc.h engine.h graph.h \ @@ -68,8 +75,8 @@ $(OBJDIR)/saveini.o: saveini.c const.h global.h struct.h readini.h io.h errors.h $(OBJDIR)/sdlscreen.o: sdlscreen.c global.h struct.h const.h sdlscreen.h errors.h \ misc.h $(OBJDIR)/setup.o: setup.c struct.h const.h io.h setup.h -$(OBJDIR)/shade.o: shade.c global.h struct.h const.h graph.h engine.h misc.h \ - readline.h help.h sdlscreen.h windows.h input.h shade.h +$(OBJDIR)/shade.o: shade.c global.h struct.h const.h graph.h engine.h errors.h \ + misc.h readline.h help.h sdlscreen.h windows.h input.h shade.h $(OBJDIR)/special.o: special.c const.h struct.h global.h graph.h engine.h windows.h \ special.h pages.h misc.h buttons.h $(OBJDIR)/text.o: text.c SFont.h struct.h const.h global.h sdlscreen.h io.h \ @@ -78,5 +85,5 @@ $(OBJDIR)/transform.o: transform.c global.h struct.h const.h transform.h engine. sdlscreen.h windows.h input.h help.h misc.h readline.h buttons.h \ pages.h $(OBJDIR)/version.o: version.c -$(OBJDIR)/windows.o: windows.c windows.h struct.h const.h global.h graph.h engine.h \ - misc.h sdlscreen.h errors.h input.h +$(OBJDIR)/windows.o: windows.c windows.h struct.h const.h engine.h errors.h \ + global.h graph.h input.h misc.h readline.h sdlscreen.h 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.c b/buttons.c index 2b5c91a4..28b3baf3 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; @@ -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(); @@ -715,43 +715,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); @@ -795,15 +767,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); @@ -817,43 +780,36 @@ 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 - // 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); @@ -874,54 +830,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); @@ -951,15 +898,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; @@ -968,7 +915,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(); @@ -1016,13 +963,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; @@ -1031,12 +978,13 @@ 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"))) + 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; @@ -1044,7 +992,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)); } } @@ -1056,11 +1005,17 @@ 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); + Print_in_window(x, y, current_item->Short_name, MC_Black, + (highlighted)?MC_Dark:MC_Light); } } +#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) { @@ -1071,13 +1026,23 @@ 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; + + 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 + + // 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. @@ -1085,8 +1050,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 @@ -1094,48 +1059,64 @@ void Button_Skins(void) Sort_list_of_files(&Font_files_list); selected_font = Find_file_in_fileselector(&Font_files_list, Config.Font_file); + // -------------------------------------------------------------- - 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); + 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(6,136, 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( - // 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(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); // 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(62,136, 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,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(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, 87, 14, 14, + (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 + 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); - Update_window_area(0,0,Window_width, Window_height); + 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]); + + Update_window_area(0, 0, Window_width, Window_height); Display_cursor(); @@ -1145,175 +1126,118 @@ void Button_Skins(void) switch(clicked_button) { - case 1 : // OK - break; + 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; - // 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) + // (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 { - 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; - } + Verbose_error_message(Gui_loading_error_message); + // Update preview + Window_rectangle(6, 14, 173, 16, MC_Light); } else - *quicksearch_filename=0; - */ + { + // 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(6, 14, 173, 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; } } while ( (clicked_button!=1) && (clicked_button !=6) && (Key != SDLK_ESCAPE)); if(clicked_button == 1) { - T_Gui_skin * gfx; 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 + if (gfx != NULL) { - Verbose_error_message(Gui_loading_error_message); - } - else - { - free(Gfx); - Gfx = gfx; - - free(Config.Skin_file); - Config.Skin_file = strdup(skinsdir); + 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.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); + + } + 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(); @@ -1323,14 +1247,9 @@ void Button_Skins(void) //---------------------------- Changement de page ---------------------------- void Button_Page(void) { - byte factor_index; + 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 @@ -1616,30 +1535,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); } @@ -2812,7 +2731,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; @@ -5709,7 +5628,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/buttons.h b/buttons.h index 7c38d05e..bb2d2187 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/const.h b/const.h index 4435b268..a18ddac7 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/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. diff --git a/engine.c b/engine.c index 67b4f404..6b040a9b 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 @@ -80,7 +80,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 e3de8d0f..14b84244 100644 --- a/engine.h +++ b/engine.h @@ -49,38 +49,44 @@ 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); 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/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 new file mode 100644 index 00000000..e0ebd24d --- /dev/null +++ b/factory.c @@ -0,0 +1,229 @@ +/* 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 "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" +#include "windows.h" + +#ifdef __ENABLE_LUA__ + +#include +#include + +// Wrapper functions to call C from Lua + +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_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),1); + 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), + lua_tonumber(L, 4)); + return 0; +} + +int L_GetColor(lua_State* L) +{ + T_Components couleur; + couleur = Main_palette[(int)(lua_tonumber(L,1))]; + + lua_pushinteger(L, couleur.R); + lua_pushinteger(L, couleur.G); + lua_pushinteger(L, couleur.B); + return 3; +} + +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(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(); + + do { + clicked_button = Window_clicked_button(); + + switch (clicked_button) + { + default: + break; + } + + } while (clicked_button <= 0 || clicked_button >= 3); + + if (clicked_button == 2) // Run the script + { + lua_State* L = lua_open(); + + 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); + lua_register(L,"getcolor",L_GetColor); + lua_register(L,"brushenable",L_BrushEnable); + + // For debug only + // luaL_openlibs(L); + + 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)); + + lua_close(L); + } + + Close_window(); + Unselect_button(BUTTON_BRUSH_EFFECTS); + 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/fileformats.c b/fileformats.c new file mode 100644 index 00000000..ab7c1f51 --- /dev/null +++ b/fileformats.c @@ -0,0 +1,3557 @@ +/* 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(T_GIF_IDB *idb, byte color) +{ + if (color != Main_backups->Pages->Transparent_color) // transparent color + Pixel_load_function(idb->Pos_X+GIF_pos_X, idb->Pos_Y+GIF_pos_Y,color); + + GIF_pos_X++; + + if (GIF_pos_X>=idb->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>=idb->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; + T_GIF_GCE GCE; + + 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_identifier; // 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 // + + + 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; + + Init_preview(LSDB.Width,LSDB.Height,file_size,FORMAT_GIF,PIXEL_SIMPLE); + Main_image_width=LSDB.Width; + Main_image_height=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) + + 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 + if ( Read_byte(GIF_file,&(GCE.Packed_fields)) + && Read_word_le(GIF_file,&(GCE.Delay_time)) + && Read_byte(GIF_file,&(GCE.Transparent_color))) + { + if (GCE.Packed_fields & 1) + Main_backups->Pages->Transparent_color= GCE.Transparent_color; + else + Main_backups->Pages->Transparent_color = -1; + + } + else + File_error=2; + break; + + 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 && Pixel_load_function==Pixel_load_in_current_screen) + { + // This a second layer/frame, or more. + // Attempt to add a layer to current image + Add_layer(Main_backups, Main_current_layer+1); + } + 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) + { + + // 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(&IDB, 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(&IDB, 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!=IDB.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_identifier); + } + } // 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(T_GIF_IDB *idb) + { + byte temp; + + temp=Read_pixel_function(GIF_pos_X,GIF_pos_Y); + + if (++GIF_pos_X>=idb->Image_width) + { + GIF_pos_X=0; + if (++GIF_pos_Y>=idb->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_identifier; // 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 + + byte old_current_layer=Main_current_layer; + + /////////////////////////////////////////////////// FIN DES DECLARATIONS // + + File_error=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 (Write_word_le(GIF_file,LSDB.Width) && + Write_word_le(GIF_file,LSDB.Height) && + Write_byte(GIF_file,LSDB.Resol) && + Write_byte(GIF_file,LSDB.Backcol) && + Write_byte(GIF_file,LSDB.Aspect) ) + { + // 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); + + // "Netscape" animation extension + // Write_bytes(GIF_file,"\x21\xFF\x0BNETSCAPE2.0\x03\xLL\xSS\xSS\x00",19); + // LL : 01 to loop + // SSSS : number of loops + + // 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); + } + + // Loop on all layers + for (Main_current_layer=0; + Main_current_layer < Main_backups->Pages->Nb_layers && !File_error; + Main_current_layer++) + { + // Write a Graphic Control Extension + char * GCE_block = "\x21\xF9\x04\x05\x05\x00\x00\x00"; + //if (Main_current_layer > 0) + // GCE_block[3] = '\x05'; + if (Main_current_layer == Main_backups->Pages->Nb_layers -1) + { + // "Infinite" delay for last frame + GCE_block[4] = 255; + GCE_block[5] = 255; + } + if (Write_bytes(GIF_file,GCE_block,8)) + { + + // On va écrire un block indicateur d'IDB et l'IDB du fichier + block_identifier=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 ( Write_byte(GIF_file,block_identifier) && + Write_word_le(GIF_file,IDB.Pos_X) && + Write_word_le(GIF_file,IDB.Pos_Y) && + Write_word_le(GIF_file,IDB.Image_width) && + Write_word_le(GIF_file,IDB.Image_height) && + Write_byte(GIF_file,IDB.Indicator) && + Write_byte(GIF_file,IDB.Nb_bits_pixel)) + { + // Le block indicateur d'IDB et l'IDB ont étés correctements + // écrits. + + Init_write_buffer(); + GIF_pos_X=0; + GIF_pos_Y=0; + GIF_last_byte=0; + GIF_remainder_bits=0; + GIF_remainder_byte=0; + + 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(&IDB); + descend=1; + + do + { + current_char=GIF_next_pixel(&IDB); + + // 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 #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]; @@ -122,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; @@ -146,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++; @@ -176,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++) @@ -208,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; @@ -223,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; @@ -270,7 +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); + gfx->Color_black = Get_SDL_pixel_8(gui,cursor_x,cursor_y); do { if (++cursor_x>=gui->w) @@ -279,9 +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; + gfx->Color_dark = color; do { if (++cursor_x>=gui->w) @@ -290,9 +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; + gfx->Color_light = color; do { if (++cursor_x>gui->w) @@ -301,9 +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; + gfx->Color_white = color; do { if (++cursor_x>=gui->w) @@ -312,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) @@ -323,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) @@ -343,8 +344,14 @@ 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(gfx, gui, cursor_x, cursor_y, gfx->Preview, 173, 16, "logo", 0)) + return 1; cursor_y+=MENU_HEIGHT; // Effets @@ -360,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; } @@ -379,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; @@ -399,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; } @@ -421,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; } @@ -440,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; } @@ -450,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; @@ -467,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; } @@ -489,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; } @@ -511,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; } @@ -546,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; @@ -1058,10 +1062,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); @@ -2464,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/loadsave.c b/loadsave.c index 8aabc8e0..5395efcd 100644 --- a/loadsave.c +++ b/loadsave.c @@ -27,10 +27,8 @@ #include #include #include -#ifndef __no_pnglib__ -#include -#endif #include +#include #include "buttons.h" #include "const.h" @@ -131,6 +129,7 @@ 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, 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, 0, "", "*"}, @@ -181,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) @@ -270,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; @@ -807,6157 +799,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(T_GIF_IDB *idb, byte color) - { - if (color != Main_backups->Pages->Transparent_color) // transparent color - Pixel_load_function(idb->Pos_X+GIF_pos_X, idb->Pos_Y+GIF_pos_Y,color); - - GIF_pos_X++; - - if (GIF_pos_X>=idb->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>=idb->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; - T_GIF_GCE GCE; - - 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_identifier; // 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 // - - - 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; - - Init_preview(LSDB.Width,LSDB.Height,file_size,FORMAT_GIF,PIXEL_SIMPLE); - Main_image_width=LSDB.Width; - Main_image_height=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) - - 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 - if ( Read_byte(GIF_file,&(GCE.Packed_fields)) - && Read_word_le(GIF_file,&(GCE.Delay_time)) - && Read_byte(GIF_file,&(GCE.Transparent_color))) - { - if (GCE.Packed_fields & 1) - Main_backups->Pages->Transparent_color= GCE.Transparent_color; - else - Main_backups->Pages->Transparent_color = -1; - - } - else - File_error=2; - break; - - 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 && Pixel_load_function==Pixel_load_in_current_screen) - { - // This a second layer/frame, or more. - // Attempt to add a layer to current image - Add_layer(Main_backups, Main_current_layer+1); - } - 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) - { - - // 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(&IDB, 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(&IDB, 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!=IDB.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_identifier); - } - } // 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(T_GIF_IDB *idb) - { - byte temp; - - temp=Read_pixel_function(GIF_pos_X,GIF_pos_Y); - - if (++GIF_pos_X>=idb->Image_width) - { - GIF_pos_X=0; - if (++GIF_pos_Y>=idb->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_identifier; // 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 - - byte old_current_layer=Main_current_layer; - - /////////////////////////////////////////////////// FIN DES DECLARATIONS // - - File_error=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 (Write_word_le(GIF_file,LSDB.Width) && - Write_word_le(GIF_file,LSDB.Height) && - Write_byte(GIF_file,LSDB.Resol) && - Write_byte(GIF_file,LSDB.Backcol) && - Write_byte(GIF_file,LSDB.Aspect) ) - { - // 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); - - // "Netscape" animation extension - // Write_bytes(GIF_file,"\x21\xFF\x0BNETSCAPE2.0\x03\xLL\xSS\xSS\x00",19); - // LL : 01 to loop - // SSSS : number of loops - - // 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); - } - - // Loop on all layers - for (Main_current_layer=0; - Main_current_layer < Main_backups->Pages->Nb_layers && !File_error; - Main_current_layer++) - { - // Write a Graphic Control Extension - char * GCE_block = "\x21\xF9\x04\x05\x05\x00\x00\x00"; - //if (Main_current_layer > 0) - // GCE_block[3] = '\x05'; - if (Main_current_layer == Main_backups->Pages->Nb_layers -1) - { - // "Infinite" delay for last frame - GCE_block[4] = 255; - GCE_block[5] = 255; - } - if (Write_bytes(GIF_file,GCE_block,8)) - { - - // On va écrire un block indicateur d'IDB et l'IDB du fichier - block_identifier=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 ( Write_byte(GIF_file,block_identifier) && - Write_word_le(GIF_file,IDB.Pos_X) && - Write_word_le(GIF_file,IDB.Pos_Y) && - Write_word_le(GIF_file,IDB.Image_width) && - Write_word_le(GIF_file,IDB.Image_height) && - Write_byte(GIF_file,IDB.Indicator) && - Write_byte(GIF_file,IDB.Nb_bits_pixel)) - { - // Le block indicateur d'IDB et l'IDB ont étés correctements - // écrits. - - Init_write_buffer(); - GIF_pos_X=0; - GIF_pos_Y=0; - GIF_last_byte=0; - GIF_remainder_bits=0; - GIF_remainder_byte=0; - - 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(&IDB); - descend=1; - - do - { - current_char=GIF_next_pixel(&IDB); - - // 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; yDefault_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); + // 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: - 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; - // Font if (!(Menu_font=Load_font(Config.Font_file))) if (!(Menu_font=Load_font("font_Classic.png"))) diff --git a/misc.c b/misc.c index 955b5221..162d35b8 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) @@ -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); } @@ -782,12 +782,12 @@ unsigned long Memory_free(void) len = sizeof(maxmem); sysctl(mib,2,&maxmem,&len,NULL,0); return maxmem; -#elif defined(__BEOS__) || defined(__HAIKU__) || defined(__SKYOS__) || defined(__amigaos4__) || defined(__amigaos__) +#elif defined(__BEOS__) || defined(__HAIKU__) || defined(__SKYOS__) || defined(__amigaos4__) // No on BeOS or Haiku // AvailMem is misleading on os4 (os4 caches stuff in memory that you can still allocate) #warning "There is missing code there for your platform ! please check and correct :)" return 10*1024*1024; -#elif defined(__AROS__) || defined(__MORPHOS__) +#elif defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) return AvailMem(MEMF_ANY); #else struct sysinfo info; diff --git a/miscfileformats.c b/miscfileformats.c new file mode 100644 index 00000000..410d143a --- /dev/null +++ b/miscfileformats.c @@ -0,0 +1,2485 @@ +/* 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 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); +} + 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/palette.c b/palette.c index 33c56b20..ee65823a 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 @@ -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 @@ -841,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 @@ -853,8 +865,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, 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"); + 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 +883,26 @@ 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_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); + } - 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); // Dessin des petits effets spéciaux pour les boutons [+] et [-] Draw_thingumajig(263, 74,MC_White,-1); @@ -891,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; @@ -942,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 @@ -972,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); @@ -989,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); @@ -1005,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); @@ -1400,29 +1438,66 @@ void Button_Palette(void) break; case 11: // Reduce - memcpy(backup_palette,working_palette,sizeof(T_Palette)); - if (!image_is_backed_up) - { - Backup_layers(-1); - image_is_backed_up=1; - } - Reduce_palette(&used_colors,reduce_colors_number,working_palette,color_usage); + 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 = -1; + break; + } + if (reduce_colors_number > 0) + { + if (!image_is_backed_up) + { + Backup_layers(-1); + image_is_backed_up=1; + } - 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)); - } + Reduce_palette(&used_colors, reduce_colors_number, working_palette, + color_usage); - 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)); + 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)); + } - End_of_modification(); - need_to_remap=1; + 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; + } break; case 12: // Undo @@ -1470,19 +1545,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 +1670,7 @@ void Button_Palette(void) Set_palette(working_palette); break; - case 19 : // [-] + case 18 : // [-] if (!Palette_view_is_RGB) break; Hide_cursor(); @@ -1732,7 +1795,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 +1813,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 +1858,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 +1894,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 @@ -2028,7 +2068,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)); diff --git a/scripts/test.lua b/scripts/test.lua new file mode 100644 index 00000000..a8804d1d --- /dev/null +++ b/scripts/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 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; diff --git a/skins/skin_classic.png b/skins/skin_classic.png index 6ce4c024..76554ce5 100644 Binary files a/skins/skin_classic.png and b/skins/skin_classic.png differ diff --git a/skins/skin_modern.png b/skins/skin_modern.png index d6bf97cc..086923b9 100644 Binary files a/skins/skin_modern.png and b/skins/skin_modern.png differ diff --git a/skins/skin_remapped.png b/skins/skin_remapped.png new file mode 100644 index 00000000..30a40fed Binary files /dev/null and b/skins/skin_remapped.png differ diff --git a/struct.h b/struct.h index 68954295..193f76bc 100644 --- a/struct.h +++ b/struct.h @@ -436,6 +436,20 @@ typedef struct /// A default 256-color palette. T_Palette Default_palette; + /// Preview for displaying in the skin dialog + 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 a22377e1..3eeabb75 100644 --- a/windows.c +++ b/windows.c @@ -23,16 +23,19 @@ */ #include +#include // atoi() #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. @@ -210,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; @@ -836,6 +839,49 @@ 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(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); + Display_cursor(); + + do + { + clicked_button = Window_clicked_button(); + if (clicked_button == 1) + Readline(11, 39, str, 4, 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) @@ -864,7 +910,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; @@ -1120,7 +1166,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; @@ -2497,23 +2543,23 @@ 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 - (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 @@ -2521,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 @@ -2534,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 @@ -2564,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) @@ -2621,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(&Gfx->Preview[i][j]); } Clear_border(MC_Black); } diff --git a/windows.h b/windows.h index 7feff36f..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); @@ -70,7 +71,8 @@ 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); void Display_all_screen(void);