/* Grafx2 - The Ultimate 256-color bitmap paint program Copyright 2008 Peter Gordon 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 */ #define GLOBAL_VARIABLES #include #include #include #include #include #include #include #include // There is no WM on the GP2X... #ifndef __GP2X__ #include #endif #include "const.h" #include "struct.h" #include "global.h" #include "graph.h" #include "misc.h" #include "init.h" #include "buttons.h" #include "engine.h" #include "pages.h" #include "loadsave.h" #include "sdlscreen.h" #include "errors.h" #include "readini.h" #include "saveini.h" #include "io.h" #include "text.h" #include "setup.h" #include "windows.h" #include "brush.h" #include "palette.h" #include "realpath.h" #if defined(__WIN32__) #include #include #define chdir(dir) SetCurrentDirectory(dir) #elif defined(__macosx__) #import #import #elif defined(__FreeBSD__) #import #endif #if defined (__WIN32__) // On Windows, SDL_putenv is not present in any compilable header. // It can be linked anyway, this declaration only avoids // a compilation warning. extern DECLSPEC int SDLCALL SDL_putenv(const char *variable); #endif // filename for the current GUI skin file. static char Gui_skin_file[MAX_PATH_CHARACTERS]; //--- Affichage de la syntaxe, et de la liste des modes vidéos disponibles --- void Display_syntax(void) { int mode_index; printf("Syntax: grafx2 [] []\n\n"); printf(" can be:]\n"); printf("\t/? /h /help for this help screen\n"); printf("\t/wide to emulate a video mode with wide pixels (2x1)\n"); printf("\t/tall to emulate a video mode with tall pixels (1x2)\n"); printf("\t/double to emulate a video mode with double pixels (2x2)\n"); printf("\t/wide2 to emulate a video mode with double wide pixels (4x2)\n"); printf("\t/tall2 to emulate a video mode with double tall pixels (2x4)\n"); printf("\t/triple to emulate a video mode with triple pixels (3x3)\n"); printf("\t/quadruple to emulate a video mode with quadruple pixels (4x4)\n"); printf("\t/rgb n to reduce RGB precision from 256 to n levels\n"); printf("\t/skin to use an alternate file with the menu graphics\n"); printf("\t/mode to set a video mode\n\n"); printf("Available video modes:\n\n"); for (mode_index = 0; mode_index < Nb_video_modes; mode_index += 12) { int k; for (k = 0; k < 6; k++) { if (mode_index + k >= Nb_video_modes) break; printf("%12s",Mode_label(mode_index + k)); } puts(""); } } // ---------------------------- Sortie impromptue ---------------------------- void Error_function(int error_code, const char *filename, int line_number, const char *function_name) { T_Palette temp_palette; int index; printf("Error number %d occured in file %s, line %d, function %s.\n", error_code, filename,line_number,function_name); if (error_code==0) { // L'erreur 0 n'est pas une vraie erreur, elle fait seulement un flash rouge de l'écran pour dire qu'il y a un problème. // Toutes les autres erreurs déclenchent toujours une sortie en catastrophe du programme ! memcpy(temp_palette,Main_palette,sizeof(T_Palette)); for (index=0;index<=255;index++) temp_palette[index].R=255; Set_palette(temp_palette); SDL_Delay(500); Set_palette(Main_palette); } else { switch (error_code) { case ERROR_GUI_MISSING : printf("Error: File containing the GUI graphics is missing!\n"); printf("This program cannot run without this file.\n"); break; case ERROR_GUI_CORRUPTED : printf("Error: File containing the GUI graphics couldn't be parsed!\n"); printf("This program cannot run without a correct version of this file.\n"); break; case ERROR_INI_MISSING : printf("Error: File gfx2def.ini is missing!\n"); printf("This program cannot run without this file.\n"); break; case ERROR_MEMORY : printf("Error: Not enough memory!\n\n"); printf("You should try exiting other programs to free some bytes for Grafx2.\n\n"); break; case ERROR_FORBIDDEN_MODE : printf("Error: The requested video mode has been disabled from the resolution menu!\n"); printf("If you want to run the program in this mode, you'll have to start it with an\n"); printf("enabled mode, then enter the resolution menu and enable the mode you want.\n"); printf("Check also if the 'Default_video_mode' parameter in gfx2.ini is correct.\n"); break; case ERROR_COMMAND_LINE : printf("Error: Invalid parameter or file not found.\n\n"); Display_syntax(); break; case ERROR_SAVING_CFG : printf("Error: Write error while saving settings!\n"); printf("Settings have not been saved correctly, and the gfx2.cfg file may have been\n"); printf("corrupt. If so, please delete it and Grafx2 will restore default settings.\n"); break; case ERROR_MISSING_DIRECTORY : printf("Error: Directory you ran the program from not found!\n"); break; case ERROR_INI_CORRUPTED : printf("Error: File gfx2.ini is corrupt!\n"); printf("It contains bad values at line %d.\n",Line_number_in_INI_file); printf("You can re-generate it by deleting the file and running GrafX2 again.\n"); break; case ERROR_SAVING_INI : printf("Error: Cannot rewrite file gfx2.ini!\n"); break; case ERROR_SORRY_SORRY_SORRY : printf("Error: Sorry! Sorry! Sorry! Please forgive me!\n"); break; } SDL_Quit(); exit(error_code); } } // --------------------- Analyse de la ligne de commande --------------------- void Analyze_command_line(int argc,char * argv[]) { char *buffer ; int index; File_in_command_line=0; Resolution_in_command_line=0; Current_resolution=Config.Default_resolution; for (index=1; index 256) { Error(ERROR_COMMAND_LINE); Display_syntax(); exit(0); } Set_palette_RGB_scale(scale); } else { Error(ERROR_COMMAND_LINE); Display_syntax(); exit(0); } } else if ( !strcmp(argv[index],"/skin") ) { // GUI skin file index++; if (indexpixels))[(y*32+x)] != 255) icon_mask[(y*32+x)/8] |=0x80>>(x&7); SDL_WM_SetIcon(icon,icon_mask); free(icon_mask); SDL_FreeSurface(icon); } } // Texte Init_text(); // On initialise tous les modes vidéo Set_all_video_modes(); Pixel_ratio=PIXEL_SIMPLE; // On initialise les données sur l'état du programme: // Donnée sur la sortie du programme: Quit_is_required=0; Quitting=0; // Données sur l'état du menu: Pixel_in_menu=Pixel_in_toolbar; Menu_is_visible=1; Menu_height=MENU_HEIGHT; // Données sur les couleurs et la palette: First_color_in_palette=0; // Données sur le curseur: Cursor_shape=CURSOR_SHAPE_TARGET; Cursor_hidden=0; // Données sur le pinceau: Paintbrush_X=0; Paintbrush_Y=0; Paintbrush_shape=PAINTBRUSH_SHAPE_ROUND; Paintbrush_hidden=0; Pixel_load_function=Pixel_load_in_current_screen; // On initialise tout ce qui concerne les opérations et les effets Operation_stack_size=0; Selected_freehand_mode=OPERATION_CONTINUOUS_DRAW; Selected_line_mode =OPERATION_LINE; Selected_curve_mode =OPERATION_3_POINTS_CURVE; Effect_function=No_effect; // On initialise les infos de la loupe: Main_magnifier_mode=0; Main_magnifier_factor=DEFAULT_ZOOM_FACTOR; Main_separator_proportion=INITIAL_SEPARATOR_PROPORTION; Spare_separator_proportion=INITIAL_SEPARATOR_PROPORTION; // On initialise les infos du mode smear: Smear_mode=0; Smear_brush_width=PAINTBRUSH_WIDTH; Smear_brush_height=PAINTBRUSH_HEIGHT; // On initialise les infos du mode smooth: Smooth_mode=0; // On initialise les infos du mode shade: Shade_mode=0; // Les autres infos du Shade sont chargées avec la config Quick_shade_mode=0; // idem // On initialise les infos sur les dégradés: Gradient_pixel =Display_pixel; // Les autres infos sont chargées avec la config // On initialise les infos de la grille: Snap_mode=0; Snap_width=8; Snap_height=8; Snap_offset_X=0; Snap_offset_Y=0; // On initialise les infos du mode Colorize: Colorize_mode=0; // Mode colorize inactif par défaut Colorize_opacity=50; // Une interpolation de 50% par défaut Colorize_current_mode=0; // Par défaut, la méthode par interpolation Compute_colorize_table(); // On initialise les infos du mode Tiling: Tiling_mode=0; // Pas besoin d'initialiser les décalages car ça se fait // en prenant une brosse (toujours mis à 0). // On initialise les infos du mode Mask: Mask_mode=0; // Infos du Spray Airbrush_mode=1; // Mode Mono Airbrush_size=31; Airbrush_delay=1; Airbrush_mono_flow=10; memset(Airbrush_multi_flow,0,256); srand(time(NULL)); // On randomize un peu tout ça... // Initialisation des boutons Init_buttons(); // Initialisation des opérations Init_operations(); // Initialize the brush container Init_brush_container(); Windows_open=0; // Charger la configuration des touches Set_config_defaults(); switch(Load_CFG(1)) { case ERROR_CFG_MISSING: // Pas un problème, on a les valeurs par défaut. break; case ERROR_CFG_CORRUPTED: DEBUG("Corrupted CFG file.",0); break; case ERROR_CFG_OLD: DEBUG("Unknown CFG file version, not loaded.",0); break; } // Charger la configuration du .INI temp=Load_INI(&Config); if (temp) Error(temp); Analyze_command_line(argc,argv); Current_help_section=0; Help_position=0; // Load sprites, palette etc. strcpy(Gui_skin_file,Config.Skin_file); Gfx = Load_graphics(Gui_skin_file); if (Gfx == NULL) { Gfx = Load_graphics("skin_modern.png"); if (Gfx == NULL) { printf("%s", Gui_loading_error_message); Error(ERROR_GUI_MISSING); } } Config.Fav_menu_colors[0] = Gfx->Default_palette[Gfx->Color_black]; Config.Fav_menu_colors[1] = Gfx->Default_palette[Gfx->Color_dark]; Config.Fav_menu_colors[2] = Gfx->Default_palette[Gfx->Color_light]; Config.Fav_menu_colors[3] = Gfx->Default_palette[Gfx->Color_white]; MC_Black = Gfx->Color_black; MC_Dark = Gfx->Color_dark; MC_Light = Gfx->Color_light; MC_White = Gfx->Color_white; MC_Trans = Gfx->Color_trans; // Infos sur les trames (Sieve) Sieve_mode=0; Copy_preset_sieve(0); // Transfert des valeurs du .INI qui ne changent pas dans des variables // plus accessibles: // Let's load the colors from the skin instead ! // 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"))) { printf("Unable to open the default font file: %s\n", "font_Classic.png"); Error(ERROR_GUI_MISSING); } memcpy(Main_palette, Gfx->Default_palette, sizeof(T_Palette)); // Allocation de mémoire pour la brosse if (!(Brush =(byte *)malloc( 1* 1))) Error(ERROR_MEMORY); if (!(Smear_brush =(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY); // Pinceau if (!(Paintbrush_sprite=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY); *Paintbrush_sprite=1; Paintbrush_width=1; Paintbrush_height=1; starting_videomode=Current_resolution; Horizontal_line_buffer=NULL; Screen_width=Screen_height=Current_resolution=0; Init_mode_video( Video_mode[starting_videomode].Width, Video_mode[starting_videomode].Height, Video_mode[starting_videomode].Fullscreen, Pixel_ratio); // Windows only: move back the window to its original position. #if defined(__WIN32__) if (!Video_mode[starting_videomode].Fullscreen) { if (Config.Window_pos_x != 9999 && Config.Window_pos_y != 9999) { //RECT r; static SDL_SysWMinfo pInfo; SDL_VERSION(&pInfo.version); SDL_GetWMInfo(&pInfo); //GetWindowRect(pInfo.window, &r); SetWindowPos(pInfo.window, 0, Config.Window_pos_x, Config.Window_pos_y, 0, 0, SWP_NOSIZE); } } #endif Main_image_width=Screen_width/Pixel_width; Main_image_height=Screen_height/Pixel_height; Spare_image_width=Screen_width/Pixel_width; Spare_image_height=Screen_height/Pixel_height; // Allocation de mémoire pour les différents écrans virtuels (et brosse) if (Init_all_backup_lists(Config.Max_undo_pages+1,Screen_width,Screen_height)==0) Error(ERROR_MEMORY); // On remet le nom par défaut pour la page de brouillon car il été modifié // par le passage d'un fichier en paramètre lors du traitement précédent. // Note: le fait que l'on ne modifie que les variables globales // Brouillon_* et pas les infos contenues dans la page de brouillon // elle-même ne m'inspire pas confiance mais ça a l'air de marcher sans // poser de problèmes, alors... if (File_in_command_line) { strcpy(Spare_file_directory,Spare_current_directory); strcpy(Spare_filename,"NO_NAME.GIF"); Spare_fileformat=DEFAULT_FILEFORMAT; } // Nettoyage de l'écran virtuel (les autres recevront celui-ci par copie) memset(Main_screen,0,Main_image_width*Main_image_height); // Initialisation de diverses variables par calcul: Compute_magnifier_data(); Compute_limits(); Compute_paintbrush_coordinates(); // On affiche le menu: Display_menu(); Display_paintbrush_in_menu(); Display_sprite_in_menu(BUTTON_PAL_LEFT,18+(Config.Palette_vertical!=0)); // On affiche le curseur pour débutter correctement l'état du programme: Display_cursor(); Spare_image_is_modified=0; Main_image_is_modified=0; // Gestionnaire de signaux, quand il ne reste plus aucun espoir Init_sighandler(); // Le programme débute en mode de dessin à la main Select_button(BUTTON_DRAW,LEFT_SIDE); // On initialise la brosse initiale à 1 pixel blanc: Brush_width=1; Brush_height=1; Capture_brush(0,0,0,0,0); *Brush=MC_White; return(1); } // ------------------------- Fermeture du programme -------------------------- void Program_shutdown(void) { int return_code; // Windows only: Recover the window position. #if defined(__WIN32__) { RECT r; static SDL_SysWMinfo pInfo; SDL_GetWMInfo(&pInfo); GetWindowRect(pInfo.window, &r); Config.Window_pos_x = r.left; Config.Window_pos_y = r.top; } #else // All other targets: irrelevant dimensions. // Do not attempt to force them back on next program run. Config.Window_pos_x = 9999; Config.Window_pos_y = 9999; #endif // On libère le buffer de gestion de lignes if(Horizontal_line_buffer) free(Horizontal_line_buffer); // On libère le pinceau spécial if (Paintbrush_sprite) free(Paintbrush_sprite); // On libère les différents écrans virtuels et brosse: if(Brush) free(Brush); Set_number_of_backups(0); if(Spare_screen) free(Spare_screen); if(Main_screen) free(Main_screen); // Free the skin (Gui graphics) data if (Gfx) { free(Gfx); Gfx=NULL; } // On prend bien soin de passer dans le répertoire initial: if (chdir(Initial_directory)!=-1) { // On sauvegarde les données dans le .CFG et dans le .INI if (Config.Auto_save) { return_code=Save_CFG(); if (return_code) Error(return_code); return_code=Save_INI(&Config); if (return_code) Error(return_code); } } else Error(ERROR_MISSING_DIRECTORY); SDL_Quit(); } // -------------------------- Procédure principale --------------------------- int main(int argc,char * argv[]) { int phoenix_found=0; int phoenix2_found=0; char phoenix_filename1[MAX_PATH_CHARACTERS]; char phoenix_filename2[MAX_PATH_CHARACTERS]; if(!Init_program(argc,argv)) { Program_shutdown(); return 0; } // Test de recuperation de fichiers sauvés strcpy(phoenix_filename1,Config_directory); strcat(phoenix_filename1,"phoenix.img"); strcpy(phoenix_filename2,Config_directory); strcat(phoenix_filename2,"phoenix2.img"); if (File_exists(phoenix_filename1)) phoenix_found=1; if (File_exists(phoenix_filename2)) phoenix2_found=1; if (phoenix_found || phoenix2_found) { if (phoenix2_found) { strcpy(Main_file_directory,Config_directory); strcpy(Main_filename,"phoenix2.img"); chdir(Main_file_directory); Button_Reload(); Main_image_is_modified=1; Warning_message("Spare page recovered"); // I don't really like this, but... remove(phoenix_filename2); Button_Page(); } if (phoenix_found) { strcpy(Main_file_directory,Config_directory); strcpy(Main_filename,"phoenix.img"); chdir(Main_file_directory); Button_Reload(); Main_image_is_modified=1; Warning_message("Main page recovered"); // I don't really like this, but... remove(phoenix_filename1); } } else { if (Config.Opening_message && (!File_in_command_line)) Button_Message_initial(); if (File_in_command_line) { Button_Reload(); Resolution_in_command_line=0; } } Main_handler(); Program_shutdown(); return 0; }